Spring 中 bean 注册的源码解析

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> Spring 中 bean 注册的源码解析

前言

所谓 bean 的注册,就是把在配置文件中配置的  bean 节点加载配内存中,供后续使用。

bean的注册主要分为两个阶段,一个是准备阶段,就是对配置文件进行解析,把配置文件加载到内存中,以  Document 的形式存放;第二个阶段是对  Document 进行操作,获取其中的节点,进行解析,注册。

类图

按照惯例,在看源码之前,先来看看和 bean 注册相关的类图,所涉及到的类比较多,也是挺复杂的,类图如下所示:

Spring 中 bean 注册的源码解析

先看看每个类的主要实现,最后再根据一个栗子来看 bean 注册的主要流程。

  • **`AliasRegistry`** :定义了对别名 alias 的简单增删改等操作。
  • **`SimpleAliasRegistry`**: 它是 AliasRegistry  接口的一个实现类,使用 map 来做 alias 的的映射。
  • **`BeanDefinitionRegistry`** :继承  AliasRegistry  接口, 定义了对 BeanDefinition 的各种增删改操作。
  • **`SingletonBeanRegistry`** :定义对单例bean的注册和获取。
  • **`DefaultSingletonBeanRegistry`** :是 SingletonBeanRegistry 接口的实现。
  • **`FactoryBeanRegistrySupport`** :在 DefaultSingletonBeanRegistry 的基础上增加了对 FactoryBean 的特殊处理功能。
  • **`BeanFactory`**:定义了获取bean和bean的各种属性。
  • **`HierarchicalBeanFactory`**: 继承 BeanFactory ,扩展了获取父beanFactory。
  • **`ConfigurableBeanFactory`** :提供了配置 Factory 的各种方法。
  • **`AbstractBeanFactory`** :综合了 FactoryBeanRegistrySupport 和 ConfigurableBeanFactory 的功能。
  • **`AutowireCapableBeanFactory`**:提供创建bean,自动注入,初始化以及应用bean的后置处理器。
  • **`AbstractAutowireCapableBeanFactory`** :综合了 AbstractBeanFactory 并对接口 AutowireCapableBeanFactory 进行实现。
  • **`ListableBeanFactory`** :根据各种条件获取bean的配置清单。
  • **`ConfigurableListableBeanFactory`** :BeanFactory 的配置清单,指定忽略类型及接口。
  • **`DefaultListableBeanFactory`** :综合上述所有的功能,主要是对 bean 注册后的处理。
  • **`XmlBeanFactory`** :对 DefaultListableBeanFactory 进行扩展,主要使用自定义读取器 XmlBeanDefinitionReader 从配置文件中读取 BeanDefinition。
  • ** SimpleAliasRegistry**: 它是 AliasRegistry  接口的一个实现类,使用 map 来做 alias 的的映射。

    SingletonBeanRegistry :定义对单例bean的注册和获取。

    FactoryBeanRegistrySupport :在 DefaultSingletonBeanRegistry 的基础上增加了对 FactoryBean 的特殊处理功能。

    ** HierarchicalBeanFactory**: 继承 BeanFactory ,扩展了获取父beanFactory。

    AbstractBeanFactory :综合了 FactoryBeanRegistrySupport 和 ConfigurableBeanFactory 的功能。

    AbstractAutowireCapableBeanFactory :综合了 AbstractBeanFactory 并对接口 AutowireCapableBeanFactory 进行实现。

    ConfigurableListableBeanFactory :BeanFactory 的配置清单,指定忽略类型及接口。

    XmlBeanFactory :对 DefaultListableBeanFactory 进行扩展,主要使用自定义读取器 XmlBeanDefinitionReader 从配置文件中读取 BeanDefinition。

    BeanDefinition

    BeanDefinition 是一个接口,它是配置文件  bean 标签在 Spring 容器中的内部表现形式, bean 标签拥有的属性也会对应于  BeanDefinition 中的属性,它们是一一对应的,即一个  bean 标签对应于一个  BeanDefinition实例。 BeanDefinition 相关的类图如下:

    Spring 中 bean 注册的源码解析

    共有三个实现类,在配置文件中可以有父bean和子bean,父bean用  RootBeanDefinition 来表示,子bean用  ChildBeanDefinition 来表示,而  GenericBeanDefinition 是一个通用的 BeanDefinition

    Spring 中 bean 注册的源码解析

    AbstractBeanDefinition

    AbstractBeanDefinition 实现了 BeanDefinition 接口,在  BeanDefinition 接口中只是定义了 bean标签对应属性的  setter/getter 方法,而没有定义对应的属性,而在  AbstractBeanDefinition 类中就定义了对应的各种属性,并重写了接口的  setter/getter 方法:

    Spring 中 bean 注册的源码解析

    AliasRegistry

    AliasRegistry 定义了对别名 alias 的简单增删改等操作。

    Spring 中 bean 注册的源码解析

    SimpleAliasRegistry

    SimpleAliasRegistry它是  AliasRegistry  接口的一个实现类,使用 map 来做 alias 的的映射。

    
    public class SimpleAliasRegistry implements AliasRegistry {
        // 映射的 map
        private final MapString, String aliasMap = new ConcurrentHashMapString, 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 继承   AliasRegistry  接口, 定义了对  BeanDefinition 的各种增删改操作。

    Spring 中 bean 注册的源码解析

    SingletonBeanRegistry

    SingletonBeanRegistry 定义对单例bean的注册和获取。

    Spring 中 bean 注册的源码解析

    DefaultSingletonBeanRegistry

    DefaultSingletonBeanRegistry 是  SingletonBeanRegistry 接口的实现,主要是注册bean。该类中定义了许多的 集合,用于注册

    
    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 MapString, Object singletonObjects = new ConcurrentHashMapString, Object(256);
        // 单例对应的工厂缓存,可以使用工厂来创建单例对象 bean name -- ObjectFactory
        private final MapString, ObjectFactory? singletonFactories = new HashMapString,ObjectFactory?(16);
        // 之前的单例对象
        private final MapString, Object earlySingletonObjects = new HashMapString, Object(16);
        // 已经注册过了的单例对象
        private final SetString registeredSingletons = new LinkedHashSetString(256);
        // 当前正在创建的单例对象集合
        private final SetString singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMapString, Boolean(16));
    
        // 需要排除的单例,什么意思呢?在创建单例的时候,如果该单例正在创建,就不会再创建了,就应该排除掉,如果某个单例在该集合中,则表示该单例正在创建
        private final SetString inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMapString, 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 它是访问  Spring 容器的根接口,定义了获取bean的各种重载方法:

    Spring 中 bean 注册的源码解析

    AbstractBeanFactory

    AbstractBeanFactory ,它是  BeanFactory 接口的一个抽象实现类,即 综合了  FactoryBeanRegistrySupport 和  ConfigurableBeanFactory 的功能。

    
    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    
        // bean的后置处理器 BeanPostProcessor 的集合
        private final ListBeanPostProcessor beanPostProcessors = new ArrayListBeanPostProcessor();
        // 当前正在创建的bean的名称集合
        private final ThreadLocalObject prototypesCurrentlyInCreation = new NamedThreadLocalObject("Prototype beans currently in creation");
        // 其他属性
    
        // 获取bean
        @Override
        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }
        public  T getBean(String name, Class requiredType, Object... args) throws BeansException{
            return doGetBean(name, requiredType, args, false);
        }
        // 获取bean,比较复杂,后面介绍了bean注册过,在来看
        protected  T doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {
          // 后面分析
        }
        // 其他方法
    }
    

    AbstractAutowireCapableBeanFactory

    它继承了  AbstractBeanFactory 并对接口  AutowireCapableBeanFactory 进行实现,它提供bean创建,属性填充,自动装配和初始化。 处理运行时bean引用,解析托管集合,调用初始化方法等。此外,它可以按照构造函数,名称和类型来自动装配。

    该类后面再分析bean的加载时在分析

    DefaultListableBeanFactory

    在使用 bean 之前,会先注册所有的 bean,注册的 bean 就是以 map 的形式放在该类中。从上面的类图中也可以看到,该类实现了或者说继承了两种不同的接口和抽象类,一种是和注册相关的接口和抽象类,一种是和获取bean相关的接口,现在只关心和bean注册相关的部分:

    先来看看它定义的一些属性:

    
    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    
        // 序列化相关
        private static final MapString, ReferenceDefaultListableBeanFactory serializableFactories =
                new ConcurrentHashMapString, ReferenceDefaultListableBeanFactory(8);
        private String serializationId;
    
        // 当有相同名称不同实例时是否允许覆盖,默认允许
        private boolean allowBeanDefinitionOverriding = true;
        // 对于赖加载的bean,是否允许立即加载
        private boolean allowEagerClassLoading = true;
    
        // bean 注册的缓存,注册的bean就放在该集合中
        private final MapString, BeanDefinition beanDefinitionMap = new ConcurrentHashMapString, BeanDefinition(256);
    
        // 根据类型来返回所有bean的name,包含单例和原型两种模式的bean
        private final MapClass?, String[] allBeanNamesByType = new ConcurrentHashMapClass?, String[](64);
        // 根据类型返回bean的name,只是返回单例的bean
        private final MapClass?, String[] singletonBeanNamesByType = new ConcurrentHashMapClass?, String[](64);
        // 注册的bean的name的集合
        private volatile ListString beanDefinitionNames = new ArrayListString(256);
        // 手动注册的单例的 bean name 集合
        private volatile SetString manualSingletonNames = new LinkedHashSetString(16);
        // 在冻结配置的情况下缓存bean定义名称数组
         private volatile String[] frozenBeanDefinitionNames;
        // 是否可以为所有bean缓存bean 的元数据
        private volatile boolean configur
    

    接下来看下和bean注册相关的方法:

    
    @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 这个集合
                    ListString updatedDefinitions = new 
     ArrayListString(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        // 安全的从 manualSingletonNames 集合中移除该bean
                        SetString updatedSingletons = new LinkedHashSetString(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 
                    SetString updatedSingletons = new LinkedHashSetString(this.manualSingletonNames.size() + 1);
                    updatedSingletons.addAll(this.manualSingletonNames);
                    updatedSingletons.add(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }
        else {
            //直接注册
            if (!this.beanDefinitionMap.containsKey(beanName)) {
                this.manualSingletonNames.add(beanName);
            }
        }
    }
    

    栗子

    下面通过一个栗子再来看看上面涉及到的类,熟悉 bean 注册的一个流程

    首先,来看一个 bean 配置的全部属性:

    
    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
    

    测试代码:

    
     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());
        }
    

    第一部分

    上面也说了,bean的注册主要分为两部分,第一部分加载配置文件到内存形式Document,第二部分对Document的节点进行解析,注册。这部分不过多的介绍,只需要知道配置文件加载到内存形成 Document 就可以了。
    解析配置文件的时序图如下所示:

    Spring 中 bean 注册的源码解析

    最终,注册 bean 的逻辑是从  DefaultBeanDefinitionDocumentReader 类的  parseBeanDefinitions() 方法开始的,该方法如下所示:

    
        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);
            }
        }
    

    在 Spring 的配置文件中,有两大类bean的声明,一个是默认的声明如  bean,一类是自定义的声明如  tx:annotation-driver,所以该方法分为两套解析逻辑。

    默认标签的解析

    默认标签的解析对应的是  parseDefaultElement() 方法

    
    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);
        }
    }
    
    bean 标签的解析与注册
    
    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));
        }
    }
    

    解析bean的属性和子节点

    
    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 集合中,
        ListString aliases = new ArrayListString();
        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);
            }
        }
    }
    // 其他节点的解析类似
    

    当解析完bean的所有属性和子节点后,得到  BeanDefinitionHolder  对象,该对象中包含了 bean 定义的的全部信息,之后会对该对象进行包装,为什么需要进行包装的?如果配置的bean有子节点,且该子节点是用户自定义的节点,则会对该子节点进行包装:

    
    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;
    }
    

    到这里bean的定义解析完毕了,接下来就是把解析后的bean注册到Spring容器中了:

    
    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);
            }
        }
    }
    

    到这里 bean 标签的注册已经分析完毕了,还剩下 import alias 和  beans 标签的解析,关于  alias 标签的注册,在上述分析  SimpleAliasRegistry 就分析过了,剩下的两个也是同样的套路。

    到这里,关于bean的注册就分析完毕了。

    原文始发于微信公众号(Java技术大杂烩):

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> Spring 中 bean 注册的源码解析


     上一篇
    Spring AOP 创建代理的源码解析 Spring AOP 创建代理的源码解析
    前言在上篇文章   中已经获取到了 bean 的对应增强器,之后,就可以创建对应的代理了, Spring AOP 底层使用的是 JDK 动态代理和 CGLIB 的代理,在什么情况下使用 JDK动态代理,什么时候使用 CGLIB 代理
    2021-04-05
    下一篇 
    Spring bean 创建过程源码解析 Spring bean 创建过程源码解析
    前言在上一篇文章    中分析了 Spring 中 bean 的注册过程,就是把配置文件中配置的 bean 的信息加载到内存中,以 BeanDefinition对象的形式存放,该对象中存放了 bean 的相关属性,下面就以 debug
    2021-04-05