Spring源码学习系列(三)之bean的创建

这篇来记录bean的创建以及初始化等过程。从下面getBean()方法开始,开头申明,自己推敲且水平有限,无关注释或者有说错的地方轻喷。

BeanFactory factory = new BeanFactory(new ClassPathResource("beans.xml"));
YourBean bean = factory.getBean(YourBean.class);

跟进getBean()方法发现进入了AbstractBeanFactory.doGetBean()中,方法申明如下,该方法中完成了bean的创建,依赖注入,赋值以及初始化等等..

doGetBean(final String name, @Nullable final Class requiredType, @Nullable final Object[] args, boolean typeCheckOnly) 

大概的步骤如下

  • 根据名称解析真实的beanName,比如将FactoryBean(&xxxx),alias等特殊的bean转化成正式的beanName.
        /**
         * 会将BeanDefinitionMap传递过来的alias,factoryBeanName(&FactoryBeanName)转化成实际的beanName
         */
        final String beanName = transformedBeanName(name);
  • 尝试从缓存中获取单实例bean,获取到则直接返回实例对象
        /**
         * 尝试从缓存中获取单例对象定义信息
         */
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            ....省略了一些异常信息
            /**
             * 处理FactoryBean返回的bean要是其中getObject()方法返回的对象
             */
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
  • 若默认层次的容器存在父容器,且该容器的BeanDefinition中没有该bean的定义信息那么会递归从父容器中获取bean
            /**
             * 判断该bean是否是多实例且正在创建,是则抛出异常
             */
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            //获取父IOC容器对象
            BeanFactory parentBeanFactory = getParentBeanFactory();

            //父工厂对象不为null,且当前容器工厂中没有该beanName对应的BeanDefinition,则该bean会在父容器中创建
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                //到父容器工厂递归查找
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                } else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                } else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                } else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }
  • 在正常初始化之前下先初始化依赖的bean实例,也就是dependsOn标记的
               //将GenericBeanDefinition合并为RootBeanDefinition,因为后面的操作频繁使用到RootBeanDefinition的属性
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 
                checkMergedBeanDefinition(mbd, beanName, args);
                //获取到所有的依赖beanName
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) { 
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {//校验是否循环依赖
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName); //注册依赖bean
                        try {
                            getBean(dep); //实例化依赖bean
                        } catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }
  • 正式初始化单实例bean
                // 正式实例化bean
                if (mbd.isSingleton()) {
                    //通过创建Bean得到的ObjectFactory来获取单实例bean
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
               //这里为创建bean的核心方法 -> 将返回ObjectFactory供 getSingleton()方法获取单实例bean
                            return createBean(beanName, mbd, args);
                        } catch (BeansException ex) {
//                          ...省略了异常处理
                        }
                    });
                    //对FactoryBean的特殊处理
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
  • 初始化多实例bean
                //实例化多实例bean
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        //前置处理,给prototypesCurrentlyInCreation中设置值,方便其他依赖bean检测是否正在实例化
                        beforePrototypeCreation(beanName);
                        //创建多实例bean
                        prototypeInstance = createBean(beanName, mbd, args);
                    } finally {
                        //后置处理,给prototypesCurrentlyInCreation移除对应的值
                        afterPrototypeCreation(beanName);
                    }
                    //对FactoryBean的特殊处理
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } 
  • 初始化其他Scope的bean,和单实例多实例大同小异,就是通过BeanDefinition判断scope的方式
                    //其他作用范围的bean的实例化方式
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            } finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  • 若需要做类型转化,则最后完成类型转化。其中requiredType可以在getBean()中申明需要返回的bean的类型
        //查看是否需要类型转化,需要的话使用convert进行转化然后返回bean
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            } catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }

大方向的步骤在上面已经全部展示,其中有几个很重要的点

  • 一开始的缓存处理
  • FactoryBean的特殊处理
  • 获取正式的单例对象bean的sharedInstance = getSingleton(beanName, objectFactory)方法的细节
  • 获取ObjectFactory的细节
  • 处理循环依赖

缓存处理

  • 因为Spring中的Bean默认是单例的,所以Spring在源码阶段为了追求性能,大量使用ConcurrentMap来做本地缓存处理,废话不多说直接进入上述源码。从AbstractBeanFactory.doGetBean()方法中跳转到该缓存处理逻辑,Spring使用了三级缓存来帮助我们初始化bean,并且用此来解决循环依赖的问题
    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //尝试从已经初始化好的单例对象Map中(SingletonObjects)获取
        Object singletonObject = this.singletonObjects.get(beanName);
        //isSingletonCurrentlyInCreation:判断是否是正在创建的bean
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                ////如果是正在被实例化的bean则直接返回
                singletonObject = this.earlySingletonObjects.get(beanName);
                //如果没有正在被实例化且允许提早引用,那么尝试在singletonFactories中获取ObjectFactory实例,从而可以解决循环依赖的问题
                if (singletonObject == null && allowEarlyReference) {
                    //尝试获取单例工厂,其中singletonFactories储存着需要提前初始化的所有的ObjectFactory
                    ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //使用单例工厂获取单例对象,同时设置到early单例缓存中
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

其中有几个需要特殊注意的属性

singletonObjects : 指的是已经完成创建的单实例bean,其申明为

    /**
     * k-> beanName v-> bean instance
     */
    private final Map singletonObjects = new ConcurrentHashMap<>(256);

singletonFactories : 缓存了创建bean的ObjectFactory对象,用来解决循环依赖,创建时机是在循环依赖bean的赋值之前,即population()

    /**
     * k-> beanName v-> bean ObjectFactory 实例工厂
     */
    private final Map> singletonFactories = new HashMap<>(16);

earlySingletonObjects : 当bean还在创建的时候会暴露出引用地址,用来判断是否循环依赖,在从singletonFactory缓存中获取到了依赖bean之后,会将bean添加进去。简化之后再次依赖的操作

    /**
     * k-> beanName v-> bean instance (bean未创建完毕也能通过getBean()获取到,用来检测循环引用)
     */
    private final Map earlySingletonObjects = new HashMap<>(16);

  • 缓存处理的主要三个步骤
//1.尝试从已经完全初始化好的单例缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
//2.若是正在创建的bean,且单例缓存中没有,那么则去二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
//3.二级缓存中没有获取到,从三级缓存中获取,若没有获取到则返回null
ObjectFactory singletonFactory = this.singletonFactor,ies.get(beanName);

FactoryBean的特殊处理,无论我们是实例化单例对象还是从缓存中获取对象,后面都需要对获取的Bean进行二次检测看是否是FactoryBean,实现方法在AbstractBeanFactory.getObjectForBeanInstance()方法中,主要方法源码如下

// 
        //判断是否是FactoryBean(是否以“&”开头)
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                //不是FactoryBean类型则抛出异常
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
        }
            .....省略一些缓存操作
            //使用FactoryBean.getObject方法来获取真正的bean对象,不然可能获取的factoryBean对象而不是factory-method返回的bean对象
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);

然后后面主要就是通过FactoryBeangetObject()方法来返回真正的bean对象,否则可能返回的是名字为&factoryBeanName 的bean

获取正式的单例对象bean的sharedInstance = getSingleton(beanName, objectFactory)方法的细节,主要源码如下

                    //通过创建Bean得到的ObjectFactory来获取单实例bean
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                                                  //创建bean
                            return createBean(beanName, mbd, args);
                    });

其中getSingleton就是通过第二个参数传递的函数来充当声明ObjectFactory,然后通过getObject方法实例化
这里的核心要观察createBean方法

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  //给后置处理器一个机会返回代理对象,这里会回调`InstantiationAwareBeanPostProcessor`的方法来返回代理对象
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        //创建bean的主要逻辑
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
}
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        //获取BeanInstance
        instanceWrapper = createBeanInstance(beanName, mbd, args);
        // 提早(在对属性进行赋值和初始化之前,即属性注入之前)的缓存单实例bean方便解决循环引用问题
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            //将其的引用封装到ObjectFactory中并且添加到SingletonFactory中
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        //进行属性赋值
        populateBean(beanName, mbd, instanceWrapper);
        //初始化bean并返回初始化后的bean对象
        exposedObject = initializeBean(beanName, exposedObject, mbd);
}
创建bean的核心就四大步,详细过程如图
  • createBeanInstance创建bean实例,底层通过判断构造方法,以及在getBean方法传递的参数值、BeanDefinition中申明的构造参数值来反射出实例对象
  • addSingletonFactory在给属性值赋值之前将创建好的bean添加到三级缓存中,即singletonFactories中,解决循环依赖
  • 赋值populateBean 给bean的属性填充值,若有依赖其他bean,则会递归初始化属性bean
  • initializeBean : 回调bean的初始化方法(init-method) ,afterProperties等等..
Spring源码学习系列(三)之bean的创建_第1张图片
执行流程图

解决循环依赖问题

当BeanA中有属性B,BeanB中又有属性A,则在初始化的时候就出出现循环依赖问题,如下图所示
那么Spring是怎么解决循环依赖问题呢?Spring 对使用setter/field注入的循环依赖提供解决方法,而通过构造方法的无法解决,因为在Spring创建bean的时候会使用构造方法创建bean,而此时还没有创建完成bean对象,无法进行提前缓存处理。

Spring源码学习系列(三)之bean的创建_第2张图片
循环依赖

那么在源码中两依赖bean的执行流程如下:


循环依赖流程图
  • 创建A的时候,在populateBean 给属性初始化的时候会开始创建B,并且在populateBean 方法之前会调用addSingletonFactory方法将自己的bean提交暴露在三级缓存中
  • 创建B的时候,在populateBean 给属性初始化的时候会开始创建A,发现SingleObjects容器中并没有A,则继续创建A
  • 创建A的时候,调用getSingleton从缓存中查询的时候,由于第一次已经提前将A缓存好了,那么将直接获取A的引用,从而创建B成功
  • A发现B成功,则也完成创建,又由于容器中bean是单例的,所有此时就完美的完成了循环依赖

创建bean的粗略步骤就到此结束了,谢谢大佬文章的图片,以及三层缓存的解释。

你可能感兴趣的:(Spring源码学习系列(三)之bean的创建)