Source code analysis of bean registration in Spring

Source code analysis of bean registration in Spring

TSMYK Java technology programming

Preface

The so-called bean registration is to load the <bean> node configured in the configuration file into the memory for subsequent use.

Bean registration is mainly divided into two stages. One is the preparation stage, which is to parse the configuration file, load the configuration file into the memory, and store it in the form of a Document; the second stage is to operate on the Document and obtain the nodes in it. , Parse and register.

Class Diagram

By convention, before looking at the source code, let’s take a look at the class diagram related to bean registration. There are many classes involved, and it is quite complicated. The class diagram is as follows:

Source code analysis of bean registration in Spring
First look at the main implementation of each class, and finally look at the main process of bean registration based on a chestnut.

  1. AliasRegistry: Defines simple additions, deletions, and other operations to the alias alias.

  2. SimpleAliasRegistry: It is an implementation class of the AliasRegistry interface, which uses map to map the alias.

  3. BeanDefinitionRegistry: inherits the AliasRegistry interface and defines various additions, deletions, and modifications to BeanDefinition.

  4. SingletonBeanRegistry: defines the registration and acquisition of singleton beans.

  5. DefaultSingletonBeanRegistry: is the implementation of the SingletonBeanRegistry interface.

  6. FactoryBeanRegistrySupport: On the basis of DefaultSingletonBeanRegistry, a special processing function for FactoryBean is added.

  7. BeanFactory: defines access to various properties of beans and beans.

  8. HierarchicalBeanFactory: inherits BeanFactory and extends the parent beanFactory.

  9. ConfigurableBeanFactory: Provides various methods to configure the Factory.

  10. AbstractBeanFactory: It integrates the functions of FactoryBeanRegistrySupport and ConfigurableBeanFactory.

  11. AutowireCapableBeanFactory: Provides a post processor for bean creation, automatic injection, initialization, and application of beans.

  12. AbstractAutowireCapableBeanFactory: Synthesizes AbstractBeanFactory and implements the interface AutowireCapableBeanFactory.

  13. ListableBeanFactory: Obtain the bean configuration list according to various conditions.

  14. ConfigurableListableBeanFactory: The configuration list of the BeanFactory, specifying the type and interface to be ignored.

  15. DefaultListableBeanFactory: Integrating all the above functions, mainly for processing the bean after registration.

  16. XmlBeanFactory : Extend DefaultListableBeanFactory, mainly use custom reader XmlBeanDefinitionReader to read BeanDefinition from configuration file.

BeanDefinition

BeanDefinition is an interface, it is the internal manifestation of the configuration file <bean> tag in the Spring container. The attributes of the <bean> tag will also correspond to the attributes in the BeanDefinition. They are in one-to-one correspondence, that is, a <bean> The tag corresponds to a BeanDefinition instance. The class diagram related to BeanDefinition is as follows:
Source code analysis of bean registration in Spring

There are three implementation classes. There can be parent and child beans in the configuration file. The parent bean is represented by RootBeanDefinition, the child bean is represented by ChildBeanDefinition, and GenericBeanDefinition is a general BeanDefinition.
Source code analysis of bean registration in Spring

AbstractBeanDefinition

AbstractBeanDefinition implements the BeanDefinition interface. In the BeanDefinition interface, only the setter/getter methods of the corresponding attributes of the <bean> tag are defined, but the corresponding attributes are not defined. The corresponding attributes are defined in the AbstractBeanDefinition class and rewritten Setter/getter methods of the interface:
Source code analysis of bean registration in Spring

AliasRegistry

AliasRegistry defines simple additions, deletions, and other operations to alias alias.
Source code analysis of bean registration in Spring

SimpleAliasRegistry

SimpleAliasRegistry is an implementation class of the AliasRegistry interface, which uses map to map the alias.


public class SimpleAliasRegistry implements AliasRegistry {
    // 映射的 map
    private final Map<String, String> aliasMap = new ConcurrentHashMap<String, String>(16);
    // 注册别名
    @Override
    public void registerAlias(String name, String alias) {
        synchronized (this.aliasMap) {
            // 如果真实的名字和别名相同,则把别名移除点,因为真实的名字和别名相同没有意义
            if (alias.equals(name)) {
                this.aliasMap.remove(alias);
            }
            else {
                String registeredName = this.aliasMap.get(alias);
                // 如果已经注册过了
                if (registeredName != null) {
                    // 已经注册过了且别名没有发生变化,则不处理,没有必要再注册一次
                    if (registeredName.equals(name)) {
                        return;
                    }
                    // 如果别名不允许覆盖,则抛出异常
                    if (!allowAliasOverriding()) {
                        throw new IllegalStateException("");
                    }
                }
                checkForAliasCircle(name, alias);
                // 注册别名
                this.aliasMap.put(alias, name);
            }
        }
    }
   // 其他的方法都是通过 aliasMap 来判断的
}

BeanDefinitionRegistry

BeanDefinitionRegistry inherits the AliasRegistry interface and defines various additions, deletions, and modifications to BeanDefinition.

Source code analysis of bean registration in Spring

SingletonBeanRegistry

SingletonBeanRegistry defines the registration and acquisition of singleton beans.
Source code analysis of bean registration in Spring

DefaultSingletonBeanRegistry

DefaultSingletonBeanRegistry is an implementation of the SingletonBeanRegistry interface, mainly for registering beans. Many collections are defined in this class for registration


public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    // 如果bean为null则使用 NULL_OBJECT 来站位
    protected static final Object NULL_OBJECT = new Object();
    // 单例对象缓存,bean name --> bean instance
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object(256);
    // 单例对应的工厂缓存,可以使用工厂来创建单例对象 bean name --> ObjectFactory
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String,ObjectFactory<?>>(16);
    // 之前的单例对象
    private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
    // 已经注册过了的单例对象
    private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);
    // 当前正在创建的单例对象集合
    private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));

    // 需要排除的单例,什么意思呢?在创建单例的时候,如果该单例正在创建,就不会再创建了,就应该排除掉,如果某个单例在该集合中,则表示该单例正在创建
    private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
    // ..... 其他的集合 .....

   // 注册单实例的bean
    @Override
    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        // 加锁:为什么用 ConcurrentHashMap 了还需要加锁?
        synchronized (this.singletonObjects) {
            // 判断是否已经注册过了,如果注册过了,则抛出异常
            Object oldObject = this.singletonObjects.get(beanName);
            if (oldObject != null) {
                throw new IllegalStateException("...");
            }
            // 注册
            addSingleton(beanName, singletonObject);
        }
    }
    // 真正的注册逻辑,就是把bean的名称和对象放到map中
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) { 
            // 注册,如果单例对象为null,则使用 NULL_OBJECT 站位
            this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
            // 该单例对象已经注册成功,则需要从工厂集合中移除,后面不需要再次注册
            this.singletonFactories.remove(beanName);
            // 之前注册过的对象也移除
            this.earlySingletonObjects.remove(beanName);
            // 向已经注册的单例集合中添加该实例
            this.registeredSingletons.add(beanName);
        }
    }

    // 根据 beanName 获取单例对象
    @Override
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }
    // allowEarlyReference 参数是为了解决循环引用
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果该单例没有注册过,且正在注册
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                // 如果之前也没有注册过,且llowEarlyReference=true
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    // 获取该bean对应的工厂,通过工厂了创建还bean
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        // 创建成功后,需要去除
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        // 返回单例对象
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

    // 获取所有单例的name
    @Override
    public String[] getSingletonNames() {
        synchronized (this.singletonObjects) {
            return StringUtils.toStringArray(this.registeredSingletons);
        }
    }
    // 获取所有已经注册了的单例的个数
    @Override
    public int getSingletonCount() {
        synchronized (this.singletonObjects) {
            return this.registeredSingletons.size();
        }
    }

BeanFactory

BeanFactory is the root interface for accessing the Spring container and defines various overloaded methods for obtaining beans:
Source code analysis of bean registration in Spring

AbstractBeanFactory

AbstractBeanFactory, it is an abstract implementation class of the BeanFactory interface, which integrates the functions of FactoryBeanRegistrySupport and ConfigurableBeanFactory.


public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    // bean的后置处理器 BeanPostProcessor 的集合
    private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
    // 当前正在创建的bean的名称集合
    private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal<Object>("Prototype beans currently in creation");
    // 其他属性

    // 获取bean
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException{
        return doGetBean(name, requiredType, args, false);
    }
    // 获取bean,比较复杂,后面介绍了bean注册过,在来看
    protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {
      // 后面分析
    }
    // 其他方法
}

AbstractAutowireCapableBeanFactory

It inherits AbstractBeanFactory and implements the interface AutowireCapableBeanFactory, which provides bean creation, attribute filling, automatic assembly and initialization. Handle bean references at runtime, resolve managed collections, call initialization methods, etc. In addition, it can be automatically assembled according to constructor, name and type.

This class will be analyzed later when the bean is loaded.

DefaultListableBeanFactory

Before using beans, all beans are registered first, and the registered beans are placed in the class in the form of a map. It can also be seen from the above class diagram that this class implements or inherits two different interfaces and abstract classes, one is the interface and abstract class related to registration, and the other is the interface related to obtaining beans. Now only care about the part related to bean registration:

Let's take a look at some of the attributes it defines:


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

    // 序列化相关
    private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
            new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>(8);
    private String serializationId;

    // 当有相同名称不同实例时是否允许覆盖,默认允许
    private boolean allowBeanDefinitionOverriding = true;
    // 对于赖加载的bean,是否允许立即加载
    private boolean allowEagerClassLoading = true;

    // bean 注册的缓存,注册的bean就放在该集合中
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

    // 根据类型来返回所有bean的name,包含单例和原型两种模式的bean
    private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
    // 根据类型返回bean的name,只是返回单例的bean
    private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
    // 注册的bean的name的集合
    private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);
    // 手动注册的单例的 bean name 集合
    private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);
    // 在冻结配置的情况下缓存bean定义名称数组
     private volatile String[] frozenBeanDefinitionNames;
    // 是否可以为所有bean缓存bean 的元数据
    private volatile boolean configur

Next, look at the methods related to bean registration:


@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition){

    if (beanDefinition instanceof AbstractBeanDefinition) {
        // 注册前的最后一次检验,主要是对 AbstractBeanDefinition 的属性methodOverrides进行校验
        ((AbstractBeanDefinition) beanDefinition).validate();
    }
    BeanDefinition oldBeanDefinition;
    oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    // 如果已经注册该bean
    if (oldBeanDefinition != null) {
        // 如果已经注册过该bean,且设置为不允许覆盖,则抛出异常
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionStoreException();
        }
        // 如果允许覆盖,则直接注册,覆盖
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
        // 该bean还没注册,检查该工厂的bean创建阶段是否已经开始,即在此期间是否已将该bean标记为已创建。如果已经标记为创建
        if (hasBeanCreationStarted()) {
            // 无法再修改启动时集合元素(用于稳定迭代)
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                // 更新 beanDefinitionNames 这个集合
                List<String> updatedDefinitions = new 
 ArrayList<String(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                if (this.manualSingletonNames.contains(beanName)) {
                    // 安全的从 manualSingletonNames 集合中移除该bean
                    Set<String> updatedSingletons = new LinkedHashSet<String(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }
        else {
            // 如果仍然在启动注册阶段,则直接注册
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }
}

// 注册单例的bean
@Override
public void registerSingleton(String beanName, Object singletonObject) {
    // 调用父类 DefaultSingletonBeanRegistry 的方法进行注册,上面已经分析过
    super.registerSingleton(beanName, singletonObject);
    // 同样的,如果该bean已经标注为开始创建, 
    if (hasBeanCreationStarted()) {
        synchronized (this.beanDefinitionMap) {
            if (!this.beanDefinitionMap.containsKey(beanName)) {
                // 安全的更新 manualSingletonNames 
                Set<String> updatedSingletons = new LinkedHashSet<String(this.manualSingletonNames.size() + 1);
                updatedSingletons.addAll(this.manualSingletonNames);
                updatedSingletons.add(beanName);
                this.manualSingletonNames = updatedSingletons;
            }
        }
    }
    else {
        //直接注册
        if (!this.beanDefinitionMap.containsKey(beanName)) {
            this.manualSingletonNames.add(beanName);
        }
    }
}

chestnut

Let's take a look at the classes involved above through a chestnut, and be familiar with a process of bean registration

First, look at all the properties of a bean configuration:


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd"   >

    <bean id="testBean" class="main.tsmyk.pojo.MyTestBean"
          abstract="true" autowire="byName" autowire-candidate="true"
          depends-on="conversionService" destroy-method="getName"
          factory-bean="environment" factory-method=""
          init-method="getName" lazy-init="true" name="myTestBean"
          parent="environment" primary="true" scope="singleton" >
        <property name="name" value=""/>
        <constructor-arg name="a" value="a" type="TestBean" index="" ref="">
            <bean name="" />
            <map key-type="" value-type=""/>
        </constructor-arg>
        <qualifier value="a" type=""/>
        <lookup-method />
        <meta key="" value=""/>
        <replaced-method/>
    </bean>

    <alias name="testBean" alias="aaa"/>
    <import resource=""/>
</beans>

Test code:


 public static void main(String[] args){
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("myspring.xml"));
        MyTestBean testBean = (MyTestBean) beanFactory.getBean("testBean");
        System.out.println(testBean.getName());
    }

first part

As mentioned above, bean registration is mainly divided into two parts. The first part loads the configuration file into the memory form Document, and the second part parses and registers the nodes of the Document. This part is not too much introduction, you only need to know that the configuration file is loaded into the memory to form a Document.
The sequence diagram of parsing the configuration file is as follows:
Source code analysis of bean registration in Spring

Finally, the logic of registering a bean starts with the parseBeanDefinitions() method of the DefaultBeanDefinitionDocumentReader class, which is as follows:


    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        // 表示的是默认的节点
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        // 解析默认的节点
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        // 解析自定义节点
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            // 解析自定义节点
            delegate.parseCustomElement(root);
        }
    }

In the Spring configuration file, there are two types of bean declarations, one is the default declaration such as <bean>, and the other is a custom declaration such as <tx:annotation-driver>, so the method is divided into two sets of analysis logic .

Resolution of default tags

The parsing of the default label corresponds to the parseDefaultElement() method


private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // 解析 <import>
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    // 解析 <alias>
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    // 解析 <bean>
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    // 解析 <beans>
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        doRegisterBeanDefinitions(ele);
    }
}

Analysis and registration of <bean> tag


protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 解析 bean的各种属性
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        // 如果该bean包含自定义的子标签,则对自定义子标签解析
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        // 注册
        BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        // 发消息,可以忽略
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

Analyze bean properties and child nodes


public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    return parseBeanDefinitionElement(ele, null);
}
//containingBean: 父 bean
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    // id 属性
    String id = ele.getAttribute(ID_ATTRIBUTE);
    // name 属性
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    // name 属性值就是别名 alias,解析 name 的值,放到 alias 集合中,
    List<String> aliases = new ArrayList<String>();
    if (StringUtils.hasLength(nameAttr)) {
        // 这里可以看到 name 的值可以使用 , ; 和空格进行分割
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
        aliases.addAll(Arrays.asList(nameArr));
    }
    // beanName 的值就是 id 的值
    String beanName = id;
    // 如果 beanName 为空,且 alias 不为空,则获取第一个别名作为beanName
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
        beanName = aliases.remove(0);
    }
    // 如果父 bean 为空,则检查beanName的唯一性
    if (containingBean == null) {
        checkNameUniqueness(beanName, aliases, ele);
    }
    // 创建 AbstractBeanDefinition 在该方法内部,会解析bean所有的属性和子节点
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
        if (!StringUtils.hasText(beanName)) {
            // 如果 beanName为空,则根据spring中的命名规则为该bean生成对应的beanName
            if (containingBean != null) {
                beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
            }
            else {
                beanName = this.readerContext.generateBeanName(beanDefinition);
                // 把该bean的类名也注册为别名,为了向后兼容
                String beanClassName = beanDefinition.getBeanClassName();
                if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                    aliases.add(beanClassName);
                }
            }
        }
        // BeanDefinitionHolder 创建对象返回,分别设置对应的属性值
        String[] aliasesArray = StringUtils.toStringArray(aliases);
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }
    return null;
}

// 解析属性和子节点
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
    // 不知道干嘛用
    this.parseState.push(new BeanEntry(beanName));

    // 获取 class 属性的值
    String className = null;
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }
    // 获取 parent 属性的值
    String parent = null;
    if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
        parent = ele.getAttribute(PARENT_ATTRIBUTE);
    } 
    // 创建 AbstractBeanDefinition 对象,底层是 GenericBeanDefinition
    AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    // 解析所有属性
    parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
    // 解析 <meta>
    parseMetaElements(ele, bd);
    // 解析 <lookup-method />
    parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    // 解析 <replaced-method/>
    parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    // 解析 <constructor-arg />
    parseConstructorArgElements(ele, bd);
    // 解析 <property />
    parsePropertyElements(ele, bd);
    // 解析 <qualifier />
    parseQualifierElements(ele, bd);

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

    return bd;
}

// 解析所有属性
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
        BeanDefinition containingBean, AbstractBeanDefinition bd) {
    // singleton 和 scope 只能有一个
    if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
        error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
    }
    else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
        bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
    }
    else if (containingBean != null) {
        bd.setScope(containingBean.getScope());
    }
    // abstract 属性
    if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
        bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
    }
    // lazyInit 属性
    String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
    if (DEFAULT_VALUE.equals(lazyInit)) {
        lazyInit = this.defaults.getLazyInit();
    }
    bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
    // 其他属性
}

// 解析 <meta>
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
    NodeList nl = ele.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        // 判断是 meta 节点
        if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
            Element metaElement = (Element) node;
            String key = metaElement.getAttribute(KEY_ATTRIBUTE);
            String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
            BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
            attribute.setSource(extractSource(metaElement));
            attributeAccessor.addMetadataAttribute(attribute);
        }
    }
}
// 其他节点的解析类似

After parsing all the attributes and child nodes of the bean, you will get the BeanDefinitionHolder object, which contains all the information defined by the bean, and then the object will be packaged. Why do you need to package it? If the configured bean has a child node, and the child node is a user-defined node, the child node will be packaged:


bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
    return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
}
// 包装,containingBd:父bean
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
    // 最终的 BeanDefinitionHolder 
    BeanDefinitionHolder finalDefinition = definitionHolder;

    // 遍历所有属性,看看否是有适用于修改的属性
    NamedNodeMap attributes = ele.getAttributes();
    for (int i = 0; i < attributes.getLength(); i++) {
        Node node = attributes.item(i);
        finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
    }
    // 遍历所有子节点,看看是否有适用于修改的子节点
    NodeList children = ele.getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
        Node node = children.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
        }
    }
    return finalDefinition;
}

public BeanDefinitionHolder decorateIfRequired(
        Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
    // 获取自定义的命名空间
    String namespaceUri = getNamespaceURI(node);
    // 不是默认的命名空间,则是自定义的命名空间
    if (!isDefaultNamespace(namespaceUri)) {
        // 根据命名空间获取对应的处理器
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler != null) {
            return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
        }
    }
    return originalDef;
}

Now that the definition of the bean is parsed, the next step is to register the parsed bean in the Spring container:


BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

// 注册
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {

    // bean的名字
    String beanName = definitionHolder.getBeanName();
    // 使用 DefaultListableBeanFactory 来注册bean,即把beanName和对应的BeanDefinition 注册到map中,上面分析DefaultListableBeanFactory 类时已经分析过该方法了
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // 注册别名,调用 SimpleAliasRegistry 的 registerAlias 来注册别名,上面已经分析该类了
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

At this point, the registration of the <bean> tag has been analyzed, and there is still the analysis of the <import>, <alias> and <beans> tags. Regarding the registration of the <alias> tag, we have analyzed the SimpleAliasRegistry in the above analysis, and the rest The two are the same routine.

At this point, the analysis of bean registration is complete.

Guess you like

Origin blog.51cto.com/15077536/2608547