敖胤

绳锯木断,水滴石穿;聚沙成塔,集腋成裘。

导航

从new ClassPathXmlApplicationContext(String configLocation)浅读Spring bean加载(源码)

先放一张ClassPathXmlApplicationContext UML图

1、程序入口

获取IOC容器

BeanFactory applicationContext = new ClassPathXmlApplicationContext("org/silence/config/spring-beans.xml");

2、刷新容器

在实例化IOC容器的过程中,会调用一个refresh()方法,用来刷新IOC容器,此方法会去调用父类中的刷新方法。所有的bean会在在此方法完成后实现加载。

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
      ...
          
    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
          this(new String[] {configLocation}, true, null);
    }
    //最终容器实例化的方法
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
       super(parent);
       setConfigLocations(configLocations);
       if (refresh) {
          refresh(); //刷新IOC容器,此处会直接跳到父类中的刷新方法
       }
    }
}

3、获取beanFactory对象

调用父类AbstractXmlApplicationContext中的refresh()方法。

通过其中的obtainFreshBeanFactory()方法得到一个DefaultListableBeanFactory实例。

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        // 获取beanFactory。此方法执行完之后,xml中定义的bean就已经被加载到 IOC容器中了。
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }
		...
            
        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}


3.1、obtainFreshBeanFactory()方法

// private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

3.2、BeanFactory实例属性

执行完obtainFreshBeanFactory()方法后得到的是一个DefaultListableBeanFactory实例,bean信息以BeanDefinition实例保存在容器的缓存中。

DefaultListableBeanFactory类中的缓存属性一览。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
      implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

   /** Map from dependency type to corresponding autowired value. */
   private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

   /** Map of bean definition objects, keyed by bean name. */
   private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

   /** Map of singleton and non-singleton bean names, keyed by dependency type. */
   private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

   /** Map of singleton-only bean names, keyed by dependency type. */
   private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

}

4、开始加载bean

调用AbstractRefreshableApplicationContext中的refreshBeanFactory()方法。通过loadBeanDefinitions(beanFactory)加载bean。

protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);//加载bean
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

4.1、调用子类实现的方法

调用子类AbstractXmlApplicationContext中的loadBeanDefinitions(DefaultListableBeanFactory beanFactory)方法

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   // 实例化一个用于读取和转化xml文件内容的XmlBeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's resource loading environment.
   // 设置reader的环境属性
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // 通过beanDefinitionReader 加载bean
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}

4.2、通过reader加载bean

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);//通过reader加载bean
   }
}

5、加载bean

5.1、入口

调用AbstractBeanDefinitionReader中的loadBeanDefinitions(String... locations)

public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
   Assert.notNull(locations, "Location array must not be null");
   int count = 0;
   for (String location : locations) {
      count += loadBeanDefinitions(location);
   }
   return count;
}

5.2、将xml文件转化为Resource流对象

通过Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location),读取xml文件的内容,并将一个个的xml文件封装为Resource对象

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException(
            "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
        // Resource pattern matching available.
        try {
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            int count = loadBeanDefinitions(resources);//读取bean
            if (actualResources != null) {
                Collections.addAll(actualResources, resources);
            }
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
            }
            return count;
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                "Could not resolve bean definition resource pattern [" + location + "]", ex);
        }
    }
    else {
        // Can only load single resources by absolute URL.
        // 读取单个绝对路径的配置文件
        Resource resource = resourceLoader.getResource(location);
        int count = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
        }
        return count;
    }
}

5.3、解析xml中的内容并注册bean

在XmlBeanDefinitionReader中,通过Document doc = doLoadDocument(inputSource, resource),读取Resource流的内容,并封装为Document 对象。然后调用doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法加载bean。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {

   try {
      Document doc = doLoadDocument(inputSource, resource);
      int count = registerBeanDefinitions(doc, resource);//注册bean
      if (logger.isDebugEnabled()) {
         logger.debug("Loaded " + count + " bean definitions from " + resource);
      }
      return count;
   }
  ...
}

5.4、将XML中的标签内容封装为Element对象

调用DefaultBeanDefinitionDocumentReader中registerBeanDefinitions(Document doc, XmlReaderContext readerContext)方法。最终,通过委派方式,将Element对象交由BeanDefinitionParserDelegate解析

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
   this.readerContext = readerContext;
   doRegisterBeanDefinitions(doc.getDocumentElement());
}

protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    ...

    preProcessXml(root);//预处理xml
    parseBeanDefinitions(root, this.delegate);//解析xml中的<bean/>标签
    postProcessXml(root);//后处理xml

    this.delegate = parent;
}

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();//获取xml中的所有子标签节点
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {//判断是否为<bean/>标签
                //将xml的标签封装为Element元素  org.w3c.dom.Node->org.w3c.dom.Element
                Element ele = (Element) node;             
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate);//解析xml标签元素
                }
                else {
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {//解析import节点
        importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {//解析alias节点
        processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {//解析bean节点
        processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {//解析嵌套的bean节点
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}

5.5、解析BeanDefinitionElement

在BeanDefinitionParserDelegate中通过parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)方法,对xml文件中定义的bean做解析。

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
   String id = ele.getAttribute(ID_ATTRIBUTE);
   String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

   List<String> aliases = new ArrayList<>();
   if (StringUtils.hasLength(nameAttr)) {
      String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
      aliases.addAll(Arrays.asList(nameArr));
   }

   String beanName = id;//beanName即定义的ID值
   if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
      beanName = aliases.remove(0);
      if (logger.isTraceEnabled()) {
         logger.trace("No XML 'id' specified - using '" + beanName +
               "' as bean name and " + aliases + " as aliases");
      }
   }

   //检查ID是否唯一
   if (containingBean == null) {
      checkNameUniqueness(beanName, aliases, ele);
   }

   //通过ID解析得到beanDefinition实例
   AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
   if (beanDefinition != null) {
      if (!StringUtils.hasText(beanName)) {
         try {
            if (containingBean != null) {
               beanName = BeanDefinitionReaderUtils.generateBeanName(
                     beanDefinition, this.readerContext.getRegistry(), true);
            }
            else {
               beanName = this.readerContext.generateBeanName(beanDefinition);
               
               String beanClassName = beanDefinition.getBeanClassName();
               if (beanClassName != null &&
                     beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                     !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                  aliases.add(beanClassName);
               }
            }
            if (logger.isTraceEnabled()) {
               logger.trace("Neither XML 'id' nor 'name' specified - " +
                     "using generated bean name [" + beanName + "]");
            }
         }
         catch (Exception ex) {
            error(ex.getMessage(), ele);
            return null;
         }
      }
      String[] aliasesArray = StringUtils.toStringArray(aliases);
      return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
   }

   return null;
}

public AbstractBeanDefinition parseBeanDefinitionElement(
    Element ele, String beanName, @Nullable BeanDefinition containingBean) {

    //通过ID实例化一个BeanEntry对象,并将其放入当前BeanDefinitionParserDelegate对象的parseState对象属性的LinkedList属性中
    this.parseState.push(new BeanEntry(beanName));

    //获取<bean/>标签中定义的class属性
    String className = null;
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }
    //获取父类信息
    String parent = null;
    if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
        parent = ele.getAttribute(PARENT_ATTRIBUTE);
    }

    try {
        //通过<bean/>标签中定义的类信息创建一个bean
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);

        //解析bean对象的实例化相关信息(作用域、懒加载、依赖关系、自动注入等)
        //既<bean ... scope="singleton" lazy-init="true" primary="true" depends-on="emp" init-method="" ...>这些属性
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

        //解析bean定义中的元数据信息
        parseMetaElements(ele, bd);
        //解析覆盖的方法
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

        //解析依赖注入信息!!
        /*        
        RuntimeBeanReference ref = new RuntimeBeanReference(refName);
		ref.setSource(extractSource(ele));
		return ref;
        */
        parseConstructorArgElements(ele, bd);//解析构造器参数注入元素     
        parsePropertyElements(ele, bd);//解析属性(set)注入元素
        parseQualifierElements(ele, bd);//解析限定(Qualifier)注入元素:当容器中存在多个具有相同类型的bean时,想要用一个属性指定它们其中的一个进行装配,常见的是@Autowired联合@Qualifier("beanID")的方式

        bd.setResource(this.readerContext.getResource());
        bd.setSource(extractSource(ele));

        return bd;
    }
    catch (ClassNotFoundException ex) {
        error("Bean class [" + className + "] not found", ele, ex);
    }
    catch (NoClassDefFoundError err) {
        error("Class that bean class [" + className + "] depends on not found", ele, err);
    }
    catch (Throwable ex) {
        error("Unexpected failure during bean definition parsing", ele, ex);
    }
    finally {
        this.parseState.pop();
    }

    return null;
}

protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
    throws ClassNotFoundException {

    return BeanDefinitionReaderUtils.createBeanDefinition(
        parentName, className, this.readerContext.getBeanClassLoader());
}

5.6、获得GenericBeanDefinition对象

通过BeanDefinitionReaderUtils工具类实例化一个GenericBeanDefinition对象,并添加标签中的class信息。至此,解析加载完成

public static AbstractBeanDefinition createBeanDefinition(
      @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {

   GenericBeanDefinition bd = new GenericBeanDefinition();
   bd.setParentName(parentName);
   if (className != null) {
      if (classLoader != null) {
         //如果使用自定义的classLoader—类加载器,则通过反射加载类信息
         bd.setBeanClass(ClassUtils.forName(className, classLoader));
      }
      else {
         bd.setBeanClassName(className);
      }
   }
   return bd;
}

posted on 2021-01-11 15:46  敖胤  阅读(156)  评论(0)    收藏  举报