Spring Bean实例化过程(2)

Spring中bean的实例化的总的入口都是getBean方法

具体的实现是在AbstractBeanFactory中。

1.bean实例化的总体逻辑

getBean->doGetBean,最终的逻辑是在doGetBean中

doGetBean的大体逻辑归纳如下:

转换bean名字
 
if(原生bean实例已经实例化){
 
    判断该bean是否是FactoryBean,若是,则获取FactoryBean创建的bean。若FactoryBean是单例,则将创建的bean缓存起来。
 
}else{
 
     if(bean存在于父容器中){
 
          从父容器中获取bean实例
 
     }else{
 
          获取bean的定义信息BeanDefinition
 
          先实例化依赖的bean
 
          if(bean配置为单例){
              先创建bean的实例
              然后判断bean是否是FactoryBean,若是,则获取FactoryBean创建的bean,若FactoryBean是单例,则将创建的bean缓存起来。
          }else if(bean配置为原型){
              实例化bean的前置准备(默认实现中,是把当前beanName加入到prototypesCurrentlyInCreation集合中,用于检查循环依赖的问题)
              创建bean的实例
              实例化的后置操作(默认实现中,是把当前beanName从prototypesCurrentlyInCreation集合中删除。)
              然后判断bean是否是FactoryBean,若是,则获取FactoryBean创建的bean,若FactoryBean是单例,则将创建的bean缓存起来。
          }else{
              获取bean的scope
              采用原型bean创建的过程创建bean实例
              将bean加入到scope中
              然后判断bean是否是FactoryBean,若是,则获取FactoryBean创建的bean,若FactoryBean是单例,则将创建的bean缓存起来。
          }
}
检查bean的类型与传入参数指定类型是否一致

根据上面的逻辑可以看出,bean的实例化过程中主要是按照三种scope域进行实例化。

下面根据上面的大体逻辑把getBean分成以下几段独立逻辑分别分析。


2. 各独立逻辑模块功能分析

2.1 bean名字转换

final String beanName = transformedBeanName(name);

bean名字转换:

1.首先去除FactoryBean对应的name的前缀。这里FacotryBean实例的前缀为&,应该注意的是,FacotryBean自身是可以嵌套的,即某个FactoryBean可以由其他FactoryBean创建。

2.然后若name为别名,则获取别名对应的正真的beanName。别名的管理由SimpleAliasRegistry负责,其中提供了一个aliasMap,存储的结构为[alias,beanName]

2.2 从单例缓存中获取已经实例化的bean

1. getSingleton(),从缓存singletonObjects中获取已经实例化的bean,如果bean已经被实例化,则执行下面的逻辑:

       if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
2. 上面这段代码的主要逻辑是在getObjectForBeanInstance中,这个方法也是每个bean在实例化都会执行的一段逻辑,该方法的大体逻辑是:判断传入的bean实例是否是FactoryBean,若不是,则直接返回该实例,否则则用FactroyBean创建对应bean的实例。在后面会讲到FactoryBean实际上就是AOP和IOC容器的一个接入点。
getObjectForBeanInstance中FactoryBean处理的部分代码:

        Object object = null;
        if (mbd == null) {
            object = getCachedObjectForFactoryBean(beanName);
        }
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean factory = (FactoryBean) beanInstance;
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
这里,
1.首先尝试获取缓存的中已经被FactoryBean创建好的bean实例.
2.若没有,则判断beanName指定的配置是否在Spring容器中存在,存在则则获取merge后的BeanDefinition。这里的synthetic实际上是为了给用户自定义一些BeanDefinition注册到容器中以当作工具类来使用。对于synthetic类型的BeanDefinition,getObjectFromFactoryBean中是不会对FactoryBean生成的bean用post-processor进行后置处理的。后置处理的实现是在AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean中,它会调用容器中的BeanPostProcessor.postProcessAfterInitialization,这里提供了一个扩展点对FactoryBean生成的bean进行封装,代理等。
3.由FactoryBean创建的单例bean,spring会把它缓存起来,用于下次直接从缓存中获取。

2.3 从父容器中获取bean实例

若从当前容器中取不到已经被实例化的bean,判断bean是否在父容器中定义,若在,则从父容器中取得实例。

            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
 
            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    // Delegation to parent with explicit args.
                    return parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }
1. isPrototypeCurrentlyInCreation方法是用于循环依赖检测,spring在实例化prototype类型的bean之前,会把bean的名字加入到“正在创建的缓存”中,若bean1在创建过程依赖bean2,而bean2创建过程中同时又依赖bean1,则直接抛出异常。
在当前容器做实例化之前,会先判断bean是否由父容器来创建。若是,说明只能在父容器中找了。先还原bean的名字,然后调用父容器的getBean方法,可见,这里也是递归的过程。
这里需要注意的是,若当前容器中定义了一个名为bean1的bean,而父容器也定义了一个同名bean,这时还是会优先实例化当前容器的同名bean

2.4 实例化前的准备

if (!typeCheckOnly) {
    markBeanAsCreated(beanName);
}
 
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
 
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (int i = 0; i < dependsOn.length; i++) {
        String dependsOnBean = dependsOn[i];
        getBean(dependsOnBean);
    registerDependentBean(dependsOnBean, beanName);
}
}
这里是三类scope实例化前共有的逻辑。
1.首先,对正在进行创建的bean进行标记。
2.获取bean的merge之后的BeanDefinition
3.检查当前bean的依赖的bean,先实例化,并保存beanName依赖的bean的名字,用于在destory时能够按照顺序销毁。

2.5 实例化单例bean

if(mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
      public Object getObject() throws BeansException {
             try {
            return createBean(beanName, mbd, args);
          }
              catch (BeansException ex) {
 
            destroySingleton(beanName);
            throw ex;
          }
      }
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
1.getSingleton()是一个包含回调接口的方法,定义了创建原生bean实例的模板过程,正在的实例化bean的逻辑由外部传入的ObjectFactory接口实现。
getSingleton()模板方法中,定义了几个扩展接口beforeSingletonCreation和afterSingletonCreation,用于在实例化前后做相应的处理,在获得实例后通过addSingleton将singleton缓存起来。

getSingleton()的大致逻辑归纳如下:

基本结构
beforeSingletonCreation()
try{
    objectFactory.getObject();
}catch(Exception e){
 
}finally{
    afterSingletonCreation
}
addSingleton();
真正的创建过程的过程在AbstractAutowireCapableBeanFactory.createBean方法中。createBean方法中会产生bean实例,具体过程后面深入分析。

容器中除了FacotryBean产生的bean不是采用createBean实例化,其他bean最终的实例化都会是通过createBean来创建。

2.getObjectForBeanInstance的具体逻辑在前面已经分析,主要是对FactoryBean进行特殊处理。

2.6 实例化原型bean

          else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
原型实例化的过程实际上与单例实例化的过程类似,
a.beforePrototypeCreation把beanName加入到ThreadLocal中,可以用于避免线程重复创建该bean。
b.createBean(),与单例bean同一个执行逻辑
c.afterPrototypeCreation()清除threadLocal中的标志。

2.7 根据scope域实例化bean

如果没有指定,则从scope中创建bean
String scopeName = mbd.getScope();
final Scope scope = (Scope) this.scopes.get(scopeName);
if (scope == null) {
    throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
    Object scopedInstance = scope.get(beanName, new ObjectFactory() {
    public Object getObject() throws BeansException {
    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);
}
如果没有指定,则从scope中创建bean。

这里也是采用回调的方式,创建的原生的bean实际调用的是创建原型bean的逻辑。创建逻辑还是在createBean中。

在spring.web中AbstractRequestAttributesScope定义了get方法过程,当然我们也可以自己定义一个Scope。
public Object get(String name, ObjectFactory objectFactory) {
        RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
        Object scopedObject = attributes.getAttribute(name, getScope());
        if (scopedObject == null) {
            scopedObject = objectFactory.getObject();
            attributes.setAttribute(name, scopedObject, getScope());
        }
        return scopedObject;
    }
如果request中已经缓存了实例,直接返回,否则利用objectFactory创建bean实例,并且保存到attribute中。

2.8 创建bean

2.8.1 createBean
createBean的默认实现是在AbstractAutowireCapableBeanFactory中
               resolveBeanClass(mbd, beanName);
 
                // Prepare method overrides.
                try {
                    mbd.prepareMethodOverrides();
                }
                catch (BeanDefinitionValidationException ex) {
                    throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
                            beanName, "Validation of method overrides failed", ex);
                }
 
                try {
                    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                    Object bean = resolveBeforeInstantiation(beanName, mbd);
                    if (bean != null) {
                        return bean;
                    }
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "BeanPostProcessor before instantiation of bean failed", ex);
                }
 
                Object beanInstance = doCreateBean(beanName, mbd, args);
                if (logger.isDebugEnabled()) {
                    logger.debug("Finished creating instance of bean '" + beanName + "'");
                }
                return beanInstance;
1. resolveBeanClass()加载bean指定的class.
2. mbd.prepareMethodOverrides() 对当前bean中方法替换的设置进行验证和优化(如果一个方法覆盖器MethodOverrides只覆盖了一个方法,就通过设置重载overloaded为false来避免参数及返回值类型检查)
在spring支持两种方式的方法覆盖
一种是lookup方式,这种方式只能对不带任何参数的方法才能覆盖。

    
另一种是replace-method方式,但是需要实现MethodReplacer接口

     
                String
      
      
3. resolveBeforeInstantiation()调用InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法处理,扩展点,用于返回bean的代理对象,干涉bean的实例化。从代码中可以看到,resolveBeforeInstantiation如果创建了bean,则直接返回该实例。
4. doCreateBean 创建原生bean实例。
2.8.2 doCreateBean
doCreateBean方法的逻辑主要可以分为以下几部分
1. 创建BeanWrapper及创建后的后置处理
2. 属性注入
3. bean实例初始化
4. 对于非protype类型的bean,注册bean销毁的回调接口

第1部分:创建BeanWrapper及创建后的后置处理

        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
 
        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }

从代码中可以看到,实例化的过程中会采用BeanWrapper这样一个bean包装器对bean实例进行包装
BeanWrapper的类结构图如下:

从BeanWrapper的doc中我们可以清楚的看到这个类的主要功能:

BeanWrapper提供了设置和获取属性值(单个的或者是批量的),获取属性描述信息、查询只读或者可写属性等功能。不仅如此,BeanWrapper还支持嵌套属性,你可以不受嵌套深度限制对子属性的值进行设置。所以,BeanWrapper无需任何辅助代码就可以支持标准JavaBean的PropertyChangeListeners和VetoableChangeListeners。除此之外,BeanWrapper还提供了设置索引属性的支持。

在默认情况下,beanWrapper实例的创建会通过createBeanInstance来创建
createBeanInstance这个方法会根据三种情况来创建实例:

a. 若当前bean配置了factory-method,则采用factory-method来创建bean。

factory-method类型的bean实例,调用过程:
AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod() -> ConstructorResolver.instantiateUsingFactoryMethod()
instantiateUsingFactoryMethod()方法中代码的逻辑分为以下几块:

1. 准备BeanWrapperImpl实例
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
这里需要注意的是initBeanWrapper,该方法会拷贝一份容器中注册的PropertyEditor,用于属性类型转换。
2. 获取FactoryClass的Class对象,这里spring支持两种方式的factory-method配置方式
第一种方式--采用静态方法
第二种方式:

  

3. 得到factory-method中方法的参数值
一种是直接在getbean的时候传入
一种情况是根据配置文件中解析,解析的依据是根据返回的目标bean的构造方法需要的参数来判断的。
4. 根据factoryClass类型和传入参数,方法名称唯一确定工厂方法。
5.根据实例化策略,创建bean,这里实际上只是采用jdk的反射机制来调用factory-method方法。
6.将创建的实例放入beanWrapper实例中返回。

b. 若当前bean配置了参数或者自动注入模式为AUTOWIRE_CONSTRUCTOR或者构造方法参数不为空,则通过指定的构造函数来创建bean。

对于配置了参数的bean,的调用过程为:
AbstractAutowireCapableBeanFactory.autowireConstructor()->ConstructorResolver.autowireConstructor()
ConstructorResolver.autowireConstructor()
的逻辑与instantiateUsingFactoryMethod的逻辑基本一致
先准备BeanWrapperImpl实例,然后根据传入参数或者配置参数确定唯一的构造函数,然后反射机制调用构造函数创建对象,并将构造函数缓存起来,避免下次再进行解析匹配。
在这里需要注意的是,对应设置了lookup或这replace-method的bean,在创建对象时默认会采用cglib来创建一个代理对象以此来实现方法替换的效果。

c. 不是以上两种情况,则采用默认的无参构造函数来创建bean。

对于这类bean,创建对象的过程很简单,直接获取bean指定class中的无参构造方法,并实例化之。当然若设置了lookup或这replace-method,则创建一个当前类的代理对象。

第2部分:属性的注入

单例bean的循环依赖

在进行属性注入之前,可以看到有如下一段代码:
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, new ObjectFactory() {
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }
从代码逻辑可以看出,这里会把beanName和一个对应的ObjectFactory对象增加到singletonFactories缓存中,分析getEarlyBeanReference可以知道,它会调用SmartInstantiationAwareBeanPostProcessor这个后置处理器的getEarlyBeanReference()方法,大多数情况下,实际上相当于直接返回已经实例化的bean的引用。
为何要这样?
主要是用于解决单例bean之间存在的循环依赖,
如何实现的呢?
回到AbstractBeanFacotry.doGetBean()方法的逻辑中,我们知道在创建bean之前会先去判断当前beanName对应的bean是否已经被实例化,具体实现是在:AbstractBeanFacotry.getSingleton()方法,这个方法会依次检查不同的缓存,
Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory singletonFactory = (ObjectFactory) 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);
这里就会去检查singletonFactories中是否已经有与beanName对应的ObjectFactory,有的话,直接返回由ObjectFactory创建的对象,这里也就是正在创建过程中的bean的引用。
举个例子:如 A->B->C->A,在A创建过程中属性注入时需要B,于是实例化B,在实例化B时又需要C,因此会去先实例化C,在C属性注入过程中发现需要A,因此通过getBean(A)来实例化A,此时,A已经将其实例的引用通过ObjectFactory的方式放到singletonFactories中缓存起来了,因此直接返回,于是C可以顺利实例化,B也可以顺利完成实例化,A在得到B的实例化,即可进行下面的实例化过程。
这里需要注意的是,spring中只能解决单例bean且为setter方式的循环依赖,对于原型bean或是单例bean构造函数方式的循环依赖,spring是无法解决的,只能抛出异常了(原型bean,在spring容器中不存在缓存。单例bean构造函数方式依赖时,由于bean没有构造好,无法取得实例bean的引用)。


属性的注入逻辑封装在populateBean方法中
这个方法的逻辑是:
a. 在属性注入之前,先调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法,该接口通过返回false能中断属性的注入过程。
b. 解析bean的依赖注入方式,获取属性的值,针对AUTOWIRE_BY_NAME和AUTOWIRE_BY_TYPE进行不同处理。
若为AUTOWIRE_BY_NAME,则针对beanclass中的复杂对象属性的名字,实例化容器中对应与属性名相同的bean,并保存起来,并注册到当前bean的依赖缓存列表中。
对于AUTOWIRE_BY_TYPE,解析规则相对而言要复杂很多。
c.调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法,对属性值进行转换。这里主要的一个应用是对注解的解析如@Required注解进行支持。
d.检查bean的dependency-check参数,过滤掉dependency-check为DEPENDENCY_CHECK_NONE的属性。然后再调用InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法。然后再对属性依赖进行检查。从实现来看,checkDependencies没干啥事,这个参数作用不大。
e.用得到属性值,注入到目标对象中.这个实现是在applyPropertyValues()方法中,
applyPropertyValues()方法的大体逻辑是,通过前面解析的属性依赖实例化成具体值,具体包括ref,local和内部bean等bean依赖的实例化,以及List,Map,Set等特容器属性,然后将得到值采用TypeConvertor进行转换得到最终的属性值,最后通过BeanWrapper.setPropertyValues方法将得到的值注入到bean实例中。

第3部分 bean实例初始化
这个逻辑主要封装在initializeBean()方法中
具体代码
         protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}

		if (bean instanceof BeanClassLoaderAware) {
			((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
		}

		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(this);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			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()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}
代码逻辑很清楚包括以下几步
1.BeanNameAware,BeanClassLoaderAware,BeanFactoryAware的三个Aware接口的注入
2.applyBeanPostProcessorsBeforeInitialization() 方法,在初始化方法调用之前调用BeanPostProcessor.postProcessBeforeInitialization()方法
3.调用initMethod方法,这里主要两类init,一类是实现了InitializingBean,如果实现了,则调用它的afterPropertiesSet()方法;另外,若在bean的定义中指定了init-method方法,则调用用户自定义的init-method。注:两类init方法都存在时,会先调用InitializingBean的方法。然后再调用init-method指定的方法。
4.applyBeanPostProcessorsAfterInitialization(),这在初始化方法调用之后,会调用BeanPostProcessor.postProcessAfterInitialization()方法

第4部分 对于非protype类型的bean,注册bean销毁的回调接口
这里的销毁接口按照单例 scope和其他scope(如request,Session)进行分别注册,单例scope由spring容器负责保存注册的回调接口,其他scope由scope负责管理。
销毁接口包括三类:
第一类是用户通过bean配置中指定destroy-method指定的销毁方法。
第二类是注册了DestructionAwareBeanPostProcessor这个Bean后置处理器,则在销毁时调用该DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()
第三类是bean自身实现了DisposableBean接口,则在销毁时调用destroy方法

这三类方法的顺序为:
DestructionAwareBeanPostProcessor->DisposableBean->destroy-method

至此整个bean就已经实例化完毕。


你可能感兴趣的:(spring)