天天看点

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

在执行DefaultListableBeanFactory#preInstantiateSingletons方法时会创建非懒加载的单例Bean,这个创建过程是通过调用AbstractBeanFactory#getBean(java.lang.String)创建的;

下面分析AbstractBeanFactory#getBean(java.lang.String)的执行流程;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

该方法是一个空壳方法,没有任何的实现逻辑 真正的逻辑调用在doGetBean()中,该接口是实现了BeanFactory的getBean(String name)接口;

首先通过调用transformedBeanName(name)获取beanName;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

调用getSingleton(beanName)尝试从缓存中获取对象;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

判断条件(sharedInstance ! = null && args == null)是否成立,成立则调用getObjectForBeanInstance(sharedInstance, name, beanName, null)返回Bean实例;如果sharedInstance 是普通的单例bean,方法会直接返回bean实例;如果sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的bean实例;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

条件(sharedInstance ! = null && args == null)不成立,则走下面的逻辑;

调用isPrototypeCurrentlyInCreation(beanName)判断是否存在多例对象(prototype:多例对象,IOC容器启动的时候,IOC容器启动并不会去调用方法创建对象, 而是每次获取的时候才会调用方法创建对象)的循环依赖,存在则抛出BeanCurrentlyInCreationException异常;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

注:Spring解决了单例对象的属性注入的循环依赖,而构造器注入的循环依赖没有解决; 

创建两个循环依赖的多例Bean,如下:

  

异常如下:

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

getParentBeanFactory()判断AbstractBeanFacotry工厂是否有父工厂(一般情况下是没有父工厂因为AbstractBeanFactory直接是抽象类,不存在父工厂),存在则根据父工厂调用getBean,一般情况下,只有Spring 和SpringMvc整合的时才会有父子容器的概念;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析
AbstractBeanFactory#getBean(java.lang.String)执行流程分析

调用getMergedLocalBeanDefinition(beanName)会合并父BeanDefinition和子BeanDefinition,子BeanDefinition会覆盖父BeanDefintion;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

测试如下:

bean.xml

执行结果如下:

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

将bean.xml中注释打开,执行结果如下:

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

处理Bean加载依赖顺序,如果dependsOn不为空,则调用registerDependentBean(dep, beanName)注册该Bean的依赖项,getBean(dep)优先创建依赖的对象;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

 

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

之后根据BeanDefinition的scope类型创建Bean实例;

下面分析scope为single类型的Bean实例创建;

调用getSingleton(beanName, new ObjectFactory<Object>(){})获取单例对象;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

首先从单例缓存池中获取Bean实例,如果Bean实例存在,则将对象返回,否则执行创建对象的逻辑;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

调用beforeSingletonCreation方法标记当前bean要被创建,该方法在Bean创建前调用的;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

singletonsCurrentlyInCreation 在这里会把beanName加入进来,标记该Bean正在创建,当第二次进入时,如果出现singletonsCurrentlyInCreation 添加失败,这个时候出现了循环依赖(构造器注入);

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

ObjectFactory类型的入参singletonFactory调用getObject方法,用于返回一个Bean的实例;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

在最后会调用afterSingletonCreation将singletonsCurrentlyInCreation标记正在创建的bean从集合中移除,addSingleton将创建的Bean实例加入到缓存中

AbstractBeanFactory#getBean(java.lang.String)执行流程分析
AbstractBeanFactory#getBean(java.lang.String)执行流程分析
AbstractBeanFactory#getBean(java.lang.String)执行流程分析

而getSingleton方法的入参是一个函数接口,执行创建的逻辑在createBean方法;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

这里会调用resolveBeforeInstantiation方法,在注释中的意思是给后置处理器返回一个代理对象,但一般情况下在此次是不会返回代理对象的,不论是使用JDK代理还是Cglib代理,前提条件需要有一个Bean实例,而此时的Bean实例并没有创建,代理对象并不会生成,这里只是将用户定义的切面信息进行缓存;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

 之后执行doCreateBean方法,创建Bean实例的流程在这里;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

调用createBeanInstance方法,使用合适的实例化策略创建实例;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

判断传入的mbd.getFactoryMethodName是否为空,即有无使用@Bean通过工厂方法注入实例;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

mbd的factoryMethodName在BeanDefiniton加载时赋值的,如下: 

ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

判断Bean定义信息中的resolvedConstructorOrFactoryMethod是否缓存,因为需要根据参数确认到底使用哪个构造器,该过程比较消耗性能,所有采用缓存机制;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

通过Bean的后置处理器进行获取合适的构造器对象,根据相应的策略创建对象并返回;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

Spring中有三级缓存,用于解决属性赋值的循环依赖;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

此时创建出来的Bean没有进行属性赋值的,属于早期对象,isSingleton表示是否为单例,allowCircularReferences默认为true,isSingletonCurrentlyInCreation表示当前beanName的Bean正在创建;

符合条件则调用addSingletonFactory方法,该方法把早期对象包装成一个ObjectFactory暴露到三级缓存中;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析
AbstractBeanFactory#getBean(java.lang.String)执行流程分析

调用populateBean进行属性赋值;

对象的属性注入是通过后置处理器处理的;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

如@Autowired的属性注入是通过AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues处理的;

伪代码如下:

上面的伪代码ComponentB是ComponentA的字段值,需要自动注入;

后置处理器最终会根据注入的类型执行下面的注入逻辑,如字段的注入,执行AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject方法;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject

这里会获取字段值的实例对象,并把该字段实例对象set到依赖该对象的Bean上;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

最终通过org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate获取需要依赖的Bean的实例对象,其实该方法是通过BeanFactory#getBean获取Bean的实例对象;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

调用initializeBean进行对象初始化;

AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

invokeAwareMethods会将实现了XXXAware接口进行方法的回调,invokeInitMethods方法会将实现InitializingBean接口或@PostConstruct注解修饰的方法进行回调,applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization则会对BeanPostProcessor接口申明的方法进行回调;

AbstractBeanFactory#getBean(java.lang.String)执行流程分析

调用registerDisposableBeanIfNecessary方法,注册销毁Bean的接口DisposableBean,当Bean生命周期结束时会对该接口的destroy方法进行回调; 

AbstractBeanFactory#getBean(java.lang.String)执行流程分析
AbstractBeanFactory#getBean(java.lang.String)执行流程分析
AbstractBeanFactory#getBean(java.lang.String)执行流程分析
AbstractBeanFactory#getBean(java.lang.String)执行流程分析