spring容器之bean加载总结篇

从我们的配置文件到解析,在到对bean的beanDefinition的定义和解析过程经历了漫长的过程,最后到我们bean的创建和初始化的过程,听着就很懵逼,所以我写这篇博客的主要作用是在捋一下spring对bean的创建过程以及初始化过程,首先我们从方法入口开始:

AbstractBeanFactory.java
//获取bean
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

这是我们获取bean的入口方法,接着看:

/**
 * 返回bean的实例,
 */
  AbstractBeanFactory.java
protected  T doGetBean(final String name, @Nullable final Class requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    //该方法去掉别名之后的bean的name,如我这里有一个Student的真实的bean,别名为 Student------>aaStudent
    //Student-------->aaaaStudent,该方法内部循环处理,最终返回Student即可
    final String beanName = transformedBeanName(name);
    Object bean;

    //从上面的去掉别名的beanName拿到后,从缓存中去拿,调用了DefaultSingletonBeanRegistry的getSingleton方法
    Object sharedInstance = getSingleton(beanName);
    //这里做判断
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        //获取bean的实例
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    //这里表明上述的sharedInstance为null
    else {
        //这里分情况来看,spring考虑到了,如果当前的bean已经被创建,获取会失败,可能有别的bean在引用该bean
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        //如果容器中没有找到,则从父类容器中加载
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            //当前类的爸爸中没找到,从爷爷辈去找,直到找到
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                //调用AbstractBeanFactory的doGetBean方法去获取bean的实例
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            //args为首次创建bean的实例时的参数
            else if (args != null) {
                //使用代理的方式去获取bean实例
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            //bean的真实类型
            else if (requiredType != null) {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            //这里表示我们的args和requiredType都为null,直接通过得到的bean的名字去获取实例
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }
        //对bean的真实类型检查,在检查之前不可使用该bean
        if (!typeCheckOnly) {
            //对已经创建完的bean的实例做标记,如:已完成创建
            markBeanAsCreated(beanName);
        }

        try {
            //合并父子bean的定义
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            //检查合并之后的bean的定义
            checkMergedBeanDefinition(mbd, beanName, args);

            //先初始化当前bean所依赖的bean
            //如:我的订单类需要商品类,此刻spring会先初始化商品类,大概就是这样的
            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 + "'");
                    }
                    //给当前bean注册一个依赖bean
                    registerDependentBean(dep, beanName);
                    try {
                        //递归处理
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            //创建bean实例
            //单例的情况下
            if (mbd.isSingleton()) {
                //从缓存(singletonObjects)中去拿
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        //最后从缓存中移除对应的实例原因有:
                        //1.每当有bean在创建时,允许循环参考来解析对应的beanDefinition
                        //2.删除临时引用该bean的bean
                        destroySingleton(beanName);
                        throw ex;
                    }
                });

                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            //原型的情况下:
            else if (mbd.isPrototype()) {

                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    //创建完bean的处理
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                //获取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);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    //检查类型与实际的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());
        }
    }
    return (T) bean;
}

这是内部调用的#doGetBean(...)的方法,方法比较长,处理的逻辑比较复杂,我们简单的来总结下:

  • 首先是对我们传入的name进行转化为beanName,可能传入的name是带有别名的,不是我们想要的
//该方法去掉别名之后的bean的name,如我这里有一个Student的真实的bean,别名为 Student------>aaStudent
//Student-------->aaaaStudent,该方法内部循环处理,最终返回Student即可
final String beanName = transformedBeanName(name);

public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    //循环处理,最终获取beanName
    do {
        //获取alias
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}
  • 然后尝试着从缓存中加载单例bean
/**
 *
 * @param beanName 转化之后的bean的beanName
 * @param allowEarlyReference  允许早期依赖
 * @return
 */
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //通过beanName从缓存中去拿对应的实例
    Object singletonObject = this.singletonObjects.get(beanName);
    //如果为null且当前的单例的bean正在创建过程中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        //锁定该全局变量singletonObjects进行相关的处理
        synchronized (this.singletonObjects) {
            //从早期单例bean缓存中去获取
            singletonObject = this.earlySingletonObjects.get(beanName);
            //如果为null,且提前创建
            if (singletonObject == null && allowEarlyReference) {
                //从单例工厂中获取
                ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //调用getObject并获取对应的实例
                    singletonObject = singletonFactory.getObject();
                    //保存到earlySingletonObjects缓存中
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    //同时移除singletonFactories中的对应的objectFactory
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

上述代码分别是从缓存singletonObjects earlySingletonObjects和singletonFactories中去获取bean,同样该方法也是解决循环依赖的重要之处,我们接着看:

  • 获取bean的实例
/**
 *
 * 该方法的主要作用是获取一个bean的实例,从FactoryBean中
 * @param beanInstance 共享bean的实例
 * @param name 普通bean和有Factory前缀的bean的name
 * @param beanName 去掉别名之后的bean的name
 * @param mbd  这个是合并之后的Bean的定义的文件--->beanDefinition
 * @return 返回一个bean的object对象
 */
protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    //首先对name进行检查
    //如果name是Factory类型的(即有&开头)
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        //如果beanInstance是一个空bean类型的,直接返回一个空bean的对象
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        //如果beanInstance不是FactoryBean类型的,抛异常
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
    }

    //这里的bean可能是factory类型,也可能是正常的bean
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    //如果是factory类型的bean
    if (mbd == null) {
        //尝试从getCachedObjectForFactoryBean获取
        object = getCachedObjectForFactoryBean(beanName);
    }
    //如果从缓存中没拿到
    if (object == null) {
        //这里确定的是beanInstance是FactoryBean类型的了
        FactoryBean factory = (FactoryBean) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        //通过containsBeanDefinition方法检测
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        //判断bean的定义是否是合并之后的,不是由application容器来定义,而是用户自己定义的
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        //从FactoryBean中通过调用getObject返回一个Object对象
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    //将实例object返回
    return object;
}

这就是获取bean实例的过程,我们可以看到的是首先一进方法是对bean的类型进行判断,是一个factory类型的还是普通的bean类型,具体的方法详解请看:

  • spring容器之从bean的实例中获取对象
  • 当我们从缓存中获取的单例bean(这里的bean不成熟)不存在时,从父工厂中去加载直到找到为止
//如果容器中没有找到,则从父类容器中加载
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//当前类的爸爸中没找到,从爷爷辈去找,直到找到
String nameToLookup = originalBeanName(name);
  if (parentBeanFactory instanceof AbstractBeanFactory) {
        //调用AbstractBeanFactory的doGetBean方法去获取bean的实例
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            //args为首次创建bean的实例时的参数
            else if (args != null) {
                //使用代理的方式去获取bean实例
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            //bean的真实类型
            else if (requiredType != null) {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            //这里表示我们的args和requiredType都为null,直接通过得到的bean的名字去获取实例
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

这段代码就是递归寻找bean的过程,其核心是通过代理的方式调用#getBean(...)获取bean实例,我们接着看

  • 对bean进行类型检查
    if (!typeCheckOnly) {

    //对已经创建完的bean的实例做标记,如:已完成创建
    markBeanAsCreated(beanName);
        }

其主要是对bean的真实类型检查,在检查前该bean是不能使用的,接着是调用#markBeanAsCreated(beanName)进行其标记,避免该bean的重复创建,接着看:

  • 循环依赖的处理
//先初始化当前bean所依赖的bean
//如:我的订单类需要商品类,此刻spring会先初始化商品类,大概就是这样的
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 + "'");
                    }
        //给当前bean注册一个依赖bean
        registerDependentBean(dep, beanName);
        try {
            //递归处理
            getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

循环递归处理,首先是注册依赖等一些列操作

//单例的情况下
if (mbd.isSingleton()) {
//从缓存(singletonObjects)中去拿
sharedInstance = getSingleton(beanName, () -> {
    try {
        return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
        //最后从缓存中移除对应的实例原因有:
        //1.每当有bean在创建时,允许循环参考来解析对应的beanDefinition
        //2.删除临时引用该bean的bean
        destroySingleton(beanName);
        throw ex;
        }
    });

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

其核心方法是createBean(beanName, mbd, args),我们接着看:

  • 原型的情况下
//原型的情况下:
            else if (mbd.isPrototype()) {

                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    //创建完bean的处理
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
  • 对不同的scope进行处理
else {
                //获取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);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
  • 类型转换,如果传递的 requiredType 不为 null,则需要检测所得到 bean 的类型是否与该 requiredType 一致.如果不一致则尝试转换,当然也要能够转换成功,否则抛出 BeanNotOfRequiredTypeException 异常
//检查类型与实际的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());
        }
    }

上述过程看着很繁琐,在精简一下实质上就3步:

  • 从缓存中尝试着加载bean
  • 创建bean对象
  • 从bean实例中获取对象

关于第一步从缓存中加载bean我们在前面已经看到了,我们来看后面的两步:

创建bean实例

在上述的创建实例时我们分情况来看的,首先是单例的情况下我们看到通过#createBean(....)方法是我们创建bean的入口,接着看:

AbstractAutowireCapableBeanFactory.java

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    if (logger.isTraceEnabled()) {
        logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    //根据rootBeanDefinition和beanName去解析bean的class
    //1.如果当前bean的class被解析了
    //1.1. 克隆一份beanDefinition,主要是因为该动态解析的 class 无法保存到到共享的 BeanDefinition
    Class resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    //2.覆盖了RootBeanDefinition的prepareMethodOverrides方法
    try {
        //验证及准备覆盖的方法
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        //3. 获取一个解析之后的代理bean的实例,而不是真正的bean实例
        //给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例
        //AOP是基于此处实现的
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        //4.这里才是真正的执行创建bean的方法
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

在#createBean(...)方法中,我们首先看一下参数:

  • beanName:要创建的bean的名字
  • RootBeanDefinition:已经合并了父类属性的(如果有的话)BeanDefinition
  • args:构造函数或者工厂方法创建bean的所需参数

我们再来看一下该方法的逻辑处理过程:

  • 获取当前解析的Class属性,并进行其判断
  • 对是否覆盖了RootBeanDefinition的prepareMethodOverrides方法进行检验
  • 获取一个解析之后的代理bean的实例,而不是真正的bean实例
  • 执行创建bean的方法

看了上述的逻辑发现该方法并不是创建bean的核心方法,我们来看最后一步:

/**
 * 该方法是真正的创建bean的方法
 * @param beanName 要创建bean的名称
 * @param mbd 定义bean的beanDefinition文件
 * @param args 创建bean时,构造方法所需的参数或者是调用bean工厂时来创建bean所需的参数
 * @return 完成创建之后的bean的实例
 * @throws BeanCreationException
 */
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {

    //实例化bean的过程
    //BeanWrapper是对bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装 bean 的属性描述器
    BeanWrapper instanceWrapper = null;
    //1.如果是单例,从factoryBeanInstanceCache中移除相应的bean实例
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    //2.根据指定的bean使用对应的策略创建新的实例如:工厂方法、构造函数自动注入、简单初始化
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    //获取封装实例对象
    final Object bean = instanceWrapper.getWrappedInstance();
    //获取对应实例对象的类型
    Class beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        //将获取到的bean类型赋值给mbd的resolvedTargetType
        //resolvedTargetType用来保存真实类型bean的类型
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    //3.允许后置处理修改mbd
    synchronized (mbd.postProcessingLock) {
        //postProcessed默认为false,故不能修改,这里取反表示可以修改
        if (!mbd.postProcessed) {
            try {
                //后置处理修改beanDefinition
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    //4.对单例模式下的循环依赖进行检查
    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");
        }
        //避免后期循环依赖,提早曝光创建的bean并加入到addSingletonFactory中
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    //初始化bean实例对象
    Object exposedObject = bean;
    try {
        //5. 给bean的实例填充属性,其中,可能存在依赖于其他bean的属性,然后递归初始化bean的依赖
        populateBean(beanName, mbd, instanceWrapper);
        //6. 调用初始化方法
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }
    //7. 引用问题处理,这里先暴露早期单例引用的bean
    if (earlySingletonExposure) {
        //从缓存注册中获取,这里不允许早期引用的创建
        Object earlySingletonReference = getSingleton(beanName, false);
        //只有在检测到有依赖的情况下,earlySingletonReference才会不为null
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            //处理依赖
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    //8. 注册bean
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

该方法才是创建bean实例的核心方法,我们来看下流程:

  • 在1处,如果是单例,从factoryBeanInstanceCache中移除相应的bean实例
  • 在2处,根据指定的bean使用对应的策略创建新的实例如:工厂方法、构造函数自动注入、简单初始化,以及对创建的实例进行封装
    -在3处, 一些后置处理的过程,如:修改beanDefinition等
  • 在4处,单例模式下的循环依赖的检查等.
  • 在5处,给需要初始化的bean进行属性的填充
  • 在6处,调用#initializeBean(beanName, exposedObject, mbd)方法进型bean的初始化过程
  • 在7处,引用问题的处理的过程,spring是提前曝光要创建的bean
  • 在8处,注册 DisposableBean

接着我们来看spring通过对应的策略模式来创建bean实例的过程

实例化bean实例

如果缓存中没有 BeanWrapper 实例对象或者该 bean 不是 singleton,则调用 #createBeanInstance(...) 方法.创建 bean 实例.该方法主要是根据参数 BeanDefinition、args[] 来调用构造函数实例化 bean 对象,来看代码:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    //解析class
    Class beanClass = resolveBeanClass(mbd, beanName);
    //校验
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }
    //<1>.获取创建bean实例的回调Supplier
    Supplier instanceSupplier = mbd.getInstanceSupplier();
    //如果存在该回调,使用该回调策略来初始化bean实例
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }
    //<2>.如果工厂方法不为null,则使用工厂的方法的策略来初始化bean实例
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    //<3>. Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        //使用constructorArgumentLock
        //该constructorArgumentLock为构造函数字段常用的锁
        synchronized (mbd.constructorArgumentLock) {
            //<3.1>.resolvedConstructorOrFactoryMethod用来缓存已解析的构造函数的字段和或工厂方法
            //如果不为null
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                //对该构造参数进行标记为已解析
                //因为对于一个类可能有很多个构造函数,每个构造函数所需的参数可能不一样,所以在调用前需确定其参数方可
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    //如果解析完成,直接通过注入即可
    if (resolved) {
        //<3.2>.构造函数自动注入
        if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            //<3.3>.使用默认构造函数进行构造
            return instantiateBean(beanName, mbd);
        }
    }

    // Candidate constructors for autowiring?
    //<4>.通过参数来解析构造器
    Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    //<4.1>.当args不为null时,通过参数的个数,类型等,做精确的构造方法的选择来创建bean
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // Preferred constructors for default construction?
    //<4.2>.获取构造方法来构建bean
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // No special handling: simply use no-arg constructor.
    //<4.3>.使用默认的构造函数构造
    return instantiateBean(beanName, mbd);
}

可以从代码看到,实例化bean的过程还是有点复杂,我们拆分步骤来看:

  • 在<1>处,首先是获取创建bean实例的回调Supplier,如果存在该回调,则通过#obtainFromSupplier(instanceSupplier, beanName)方法初始化bean
  • 在<2>处,如果工厂方法不为null,则使用工厂的方法#instantiateUsingFactoryMethod(beanName, mbd, args)方法来初始化bean
  • 在<3>处,主要是判断构造参数是否已解析的过程,通过参数constructorArgumentsResolved来做的判断:
    • 在<3.1>处,首先是通过mbd的#resolvedConstructorOrFactoryMethod来判断该缓存中是否已经包含解析的构造参数或者工厂方法,如果存在,进行标记,避免重复解析
    • 在<3.2>处,如果构造参数已经解析完成则通过构造器函数自动注入的方法进行初始化bean
    • 在<3.3>处,不存在解析的构造参数,使用默认的来初始化bean
  • 在<.4>处,解析构造器,精确匹配,这里主要是通过参数来决定到底使用哪个构造器,因为一个类可能有多个构造函数
    • 在<4.1>处,如果args参数不为null,通过参数的个数,类型等,做精确的构造方法的选择来创建bean(注意:args是我们用来创建bean的参数,前面提到过)
    • 在<4.2>处,获取构造方法来构建bean
    • 在<4.3>处,使用默认的构造函数构造

其主要的核心还是根据不同的情形选择不同的策略方式来完成初始化的操作,大概有种策略方式:

  • 回调Supplier来完成初始化的操作
  • 通过工厂方法#instantiateUsingFactoryMethod(...) 方法来完成初始化
  • 通过#autowireConstructor(...)构造函数自动注入的方式来完成初始化
  • 通过#instantiateBean(...) 方法来完成初始化,这是中默认的方式

总之不管哪种方式,其逻辑都很类似,主要是通过匹配构造方法来进行初始化,对于Supplier的回调和默认的构造方法而言,工厂方法初始化和构造函数自动注入初始化会比较复杂,因为他们构造函数和构造参数的不确定性.

属性的填充

属性的填充实质就是将beanDefinition的值赋给BeanWrapper的过程,在填充过程中其主要是通过类型注入和name注入这两种方式:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    //没有被封装的bean实例
    if (bw == null) {
        //如果有属性,则抛出BeanCreationException异常
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // Skip property population phase for null instance.
            //没有可填充的属性
            return;
        }
    }

    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    //1.在属性填充前,给InstantiationAwareBeanPostProcessor最后一次来改变bean的机会
    boolean continueWithPropertyPopulation = true;
    //通过mbd.isSynthetic()来判断当前bean的定义是否是合成的,而不是由应用来定义的
    //通过hasInstantiationAwareBeanPostProcessors来判断当前bean是否持有 InstantiationAwareBeanPostProcessor
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        //循环遍历beanPostProcessors
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            //如果为InstantiationAwareBeanPostProcessor类型的
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                //赋值即可
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                //返回的值为是否为继续填充bean
                //postProcessAfterInstantiation:如果应该在 bean上面设置属性则返回 true,否则返回 false,但是一般默认为true
                //如果返回false的话,将会阻止在此 Bean实例上调用任何后续的InstantiationAwareBeanPostProcessor实例
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    //如果后续处理器发出停止填充命令,则终止后续操作
    if (!continueWithPropertyPopulation) {
        return;
    }
    //2.从rootBeanDefinition中获取bean的属性值
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    //获取resolvedAutowireMode的编码
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    //如果编码为AUTOWIRE_BY_NAME为1或者AUTOWIRE_BY_TYPE为2
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        //对PropertyValues属性进行封装成MutablePropertyValues对象
        //因为MutablePropertyValues主要是可以对构造函数进行深度的拷贝,以及属性的操作,这样可以保证我们的属性值是独立的
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        //根据名称自动注入
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        //根据类型自动注入
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }
    //是否已经初始化好后置处理器
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    //是否需要依赖检查
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    //3.bean的后置处理过程
    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        //遍历BeanPostProcessor进行处理
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            //
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                //对所有需要依赖检查的属性进行后置处理
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                //从BeanWrapper中进行PropertyDescriptor结果集的提取
                //对于PropertyDescriptor:描述一个java Bean的属性,可以通过一对方法可以提取一个属性
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
    }//4.依赖检查
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        //依赖检查,其中对应的是我们配置文件的属性depens -on属性
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }
    //5. 将属性应用到bean中
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

我们来看一下其填充属性的过程:

  • 在属性填充前,通过hasInstantiationAwareBeanPostProcessors来判断,是否需要给InstantiationAwareBeanPostProcessor最后一次来改变bean的机会
  • 获取bean的属性值,并统一保存到PropertyValues中
  • 通过参数resolvedAutowireMode来判断是通过type还是name来注入
  • 是否需要后置处理
  • 依赖检查
  • 将属性应用到bean中
初始化bean

这也是我们createBean(...)的最后一个过程,直接看代码:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction) () -> {
            //1.激活Aware,对特殊的bean进行处理,比如:Aware BeanClassLoaderAware BeanFactoryAware
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        //同上
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        //2.应用前置处理器
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        //3.激活用户自定义的init方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        //4.应用后置处理器
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}
 
 

初始化的过程很简单,其主要是通过以下流程:

  • 激活Aware,对特殊的bean进行处理
  • 应用前置处理
  • 激活用户自定义的init方法
  • 应用后置处理
从bean实例中获取对象

当我们的bean实例创建完成,还需经过最后一步,所有的都要经过此过程,就是bean的实例中获取对象,发现在getObjectForBeanInstance方法中并没有真实的处理过程只是一些准备工作,而将真正的核心处理过程交给了getObjectFromFactoryBean方法,我们来看代码:

protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {

    //先就是简单的判断,是否是单例和包含该单例bean
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            //先从缓存中去拿
            Object object = this.factoryBeanObjectCache.get(beanName);
            //这里表示没有拿到
            if (object == null) {
                //实质还是去调用getObject()去拿,这里分装了一层
                object = doGetObjectFromFactoryBean(factory, beanName);
                // Only post-process and store if not put there already during getObject() call above
                // (e.g. because of circular reference processing triggered by custom getBean calls)
                //再一次的从缓存中去获取
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                }
                else {
                    //后置处理
                    if (shouldPostProcess) {
                        //通过传入的beanName来判断当前bean是否正在创建中
                        if (isSingletonCurrentlyInCreation(beanName)) {
                            // Temporarily return non-post-processed object, not storing it yet..
                            //这里返回的是临时的非后置处理的object,并不保存它
                            return object;
                        }
                        //当前单例bean创建之前的回调该方法处理
                        beforeSingletonCreation(beanName);
                        try {

                            //对object进行后置处理,如果在FactoryBean找不到该object抛如下异常
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            //当所有的条件具备完成,最后调用该方法对单例bean创建之后的一些处理,如:不能重复创建,
                            afterSingletonCreation(beanName);
                        }
                    }
                    //进行缓存该对象
                    if (containsSingleton(beanName)) {
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            //返回从FactoryBean拿到的bean
            return object;
        }
    }
    //这里说明是factory不是单例且beanName在缓存中找不到
    else {
        //1.从factoryBean中去拿
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        //需要后置处理
        if (shouldPostProcess) {
            try {
                //从factoryBean拿到object后对其后置处理逻辑,如暴露该bean
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        //最后返回该object
        return object;
    }
}

主要过程如下:

  • 首先是从单例中获取
  • 获取锁对象,考虑到并发问题,这里锁的是 this.singletonObjects实例,其主要是保证单例bean的在spring中全局中的唯一性
  • 接着是factoryBeanObjectCache中去拿,没拿到的话,通过#doGetObjectFromFactoryBean(...)去拿,其内部还是调用FactoryBean#getObject()方法获取
  • 如果shouldPostProcess为true,说明需要后置处理:
  • 通过#isSingletonCurrentlyInCreation(...)来判断当前bean是否在创建中,如果是,则返回非处理的对象,而不是保存它
  • 通过beforeSingletonCreation(...)来进行bean实例获取之前的处理,默认是将该bean标记为当前的
  • 通过# postProcessObjectFromFactoryBean(object, beanName)进行后置处理
  • 调用 #afterSingletonCreation(String beanName) 方法,进行创建 Bean 之后的处理,默认实现是将该 bean 标记为不再在创建中
  • 最后将bean保存到factoryBeanObjectCache中

到这里关于bean的获取以及创建过程已经全部完成

你可能感兴趣的:(spring容器之bean加载总结篇)