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

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

通过调用transformedBeanName获取beanName,这里传入进来的name可能是别名alias,也有可能是工厂bean的name,所以在这里需要统一转换成beanName;
通过调用getSingleton尝试从缓存中获取对象sharedInstance ;
判断条件(sharedInstance ! = null && args == null)是否成立,如果成立,则调用getObjectForBeanInstance返回Bean实例;如果sharedInstance是普通的单例bean,getObjectForBeanInstance方法会直接返回bean实例;如果sharedInstance是FactoryBean类型的,则需调用getObject工厂方法获取真正的bean实例;
注:Spring会为FactoryBean接口的实例创建两种对象,一种是FactoryBean实例本身的对象,FactoryBean实例本身的对象是存储在一级缓存中,而另一种是FactoryBean#getObject创建的对象,该对象是存在factoryBeanObjectCache中;
条件(sharedInstance ! = null && args == null)不成立,则走下面的逻辑;

调用isPrototypeCurrentlyInCreation(beanName)判断是否存在多例对象(prototype:多例对象,IOC容器启动的时候,IOC容器启动并不会去调用方法创建对象, 而是每次获取的时候才会调用方法创建对象)的循环依赖,存在则抛出BeanCurrentlyInCreationException异常;
注:Spring解决了单例对象的属性注入的循环依赖,而构造器注入的循环依赖没有解决;
创建两个循环依赖的多例Bean,如下:
查看代码
@Scope ( "prototype" )
@Component
public class InstanceC {
private final static Log LOG = LogFactory.getLog(InstanceC. class );
@Autowired
private InstanceD instanceD;
// @Autowired
// public InstanceC(InstanceD instanceD) {
// this.instanceD = instanceD;
// }
public InstanceC() {
LOG.info( "InstanceC constructor" );
}
public void invoke() {
LOG.info( "C invoke..." );
}
public InstanceD getInstanceD() {
return instanceD;
}
}
查看代码
@Scope ( "prototype" )
@Component
public class InstanceD {
private final static Log LOG = LogFactory.getLog(InstanceD. class );
@Autowired
private InstanceC instanceC;
// @Autowired
// public InstanceD(InstanceC instanceC) {
// this.instanceC = instanceC;
// }
public void invoke() {
LOG.info( "D invoke..." );
}
public InstanceC getInstanceC() {
return instanceC;
}
}
异常如下:

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

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

测试如下:
查看代码
public class ComponentC {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this .id = id;
}
@Override
public String toString() {
return "ComponentC{" +
"name='" + name + '\ '' +
", id='" + id + '\ '' +
'}' ;
}
}
查看代码
public class ComponentD {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this .id = id;
}
@Override
public String toString() {
return "ComponentC{" +
"name='" + name + '\ '' +
", id='" + id + '\ '' +
'}' ;
}
}
bean.xml
查看代码
<?xml version= "1.0" encoding= "UTF-8" ?>
<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 = "componentC" class= "org.example.component.ComponentC" abstract= "true" >
<property name= "id" value= "test" >< /property >
<property name= "name" value= "parent" >< /property >
< /bean >
<bean id = "componentD" class= "org.example.component.ComponentD" parent= "componentC" >
<property name= "name" value= "son" >< /property >
<!-- <property name= "id" value= "componentD" >< /property >-->
< /bean >
< /beans >
查看代码
@Test
public void xmlConfigTest() {
ApplicationContext context = new ClassPathXmlApplicationContext( "bean.xml" );
System.out.println(context.getBean( "componentD" ));
}
执行结果如下:
![]()
将bean.xml中注释打开,执行结果如下:
![]()
处理Bean加载依赖顺序,如果dependsOn不为空,则调用registerDependentBean(dep, beanName)注册该Bean的依赖项,getBean(dep)优先创建依赖的对象;

测试如下:
查看代码
public class DependsA {
private final static Log LOG = LogFactory.getLog(DependsA. class );
public DependsA() {
LOG.info( "DependsA" );
}
}
查看代码
public class DependsB {
private final static Log LOG = LogFactory.getLog(DependsB. class );
public DependsB() {
LOG.info( "DependsB" );
}
}
查看代码
@Configuration
public class DependOnConfig {
@Bean
public DependsA dependsA() {
return new DependsA();
}
@Bean
@DependsOn (value = { "dependsA" })
public DependsB dependsB() {
return new DependsB();
}
}
查看代码
@Test
public void dependsOnTest() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DependOnConfig. class );
}
执行结果如下:

之后根据BeanDefinition的scope类型创建Bean实例,下面分析scope为singleton类型的Bean实例创建;
调用getSingleton(beanName, new ObjectFactory<Object>(){})获取单例对象;只有sharedInstance是FactoryBean类型的,getObjectForBeanInstance才需要调用getObject获取对象的实例,否则是直接返回的;

DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>)
首先从单例缓存池中获取Bean实例,如果Bean实例存在,则将对象返回,否则执行创建对象的逻辑;

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

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

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

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



至此,单实例Bean被Spring缓存起来了;
需要注意的是,在Spring中,只有单例对象才会被缓存起来,而多例对象(scope为prototype类型的实例)是不会执行getSingle的逻辑,也就是执行完创建后的实例不会被缓存起来,每对scope为prototype类型的实例调用一次getBean,实例都会被创建;

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

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

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

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

AbstractAutowireCapableBeanFactory#createBeanInstance根据@Autowried自动注入/调用无参构造器创建,进行相应的处理;
- instantiateBean 调用无参数的构造器进行创建对象;
- autowireConstructor @Autowired自动注入,调用构造器注入;
注:bean的实例是是通过反射创建;
Spring中有三级缓存
Spring中有三级缓存,用于解决属性赋值的循环依赖;

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

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

调用populateBean进行属性赋值
调用populateBean进行属性赋值,对象的属性注入是通过后置处理器处理的;

如@Autowired的属性注入是通过AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues处理的;
伪代码如下:
查看代码
@Component
public class ComponentA {
private final static Log LOG = LogFactory.getLog(ComponentA. class );
@Autowired
private ComponentB componentB;
public ComponentA() {
LOG.info( "ComponentA constructor" );
}
}
@Component
public class ComponentB {
private final static Log LOG = LogFactory.getLog(ComponentB. class );
public ComponentB() {
LOG.info( "ComponentB constructor" );
}
}
上面的伪代码ComponentB是ComponentA的字段值,需要自动注入;
后置处理器最终会根据注入的类型执行下面的注入逻辑,如字段的注入,执行AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject方法;

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

调用initializeBean进行对象初始化
调用initializeBean进行对象初始化;
AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

invokeAwareMethods会将实现了xxxAware接口(非忽略的自动自动装配接口)进行方法的回调,invokeInitMethods方法会将实现InitializingBean接口方法进行回调,applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization则会对BeanPostProcessor接口申明的方法进行回调;
xxxAware接口的调用
AbstractApplicationContext#prepareBeanFactory

这些接口是Spring框架提供的一种机制,用于在bean实例化之后,自动将一些特定的依赖注入到bean中;这些接口提供了访问Environment,EmbeddedValueResolver,ResourceLoader, ApplicationEventPublisher,MessageSource和ApplicationContext等Spring的核心组件的能力;然而,在prepareBeanFactory方法中,Spring容器尚未完全初始化,因此无法提供这些依赖的实例;因此,为了避免在不完全初始化的情况下注入依赖,Spring选择忽略这些自动装配的依赖接口;
非忽略自动装配xxxAware接口的调用;

其中ApplicationContextAwareProcessor#applyBeanPostProcessorsBeforeInitialization执行会执行被忽略的自动装配xxxAware接口的方法;

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

AbstractBeanFactory#getBean(java.lang.String)的大致流程图

单例Bean创建大致流程图

Bean生命周期大致流程图
根据BeanFactory的注释可以看到一个标准bean的生命周期,如下:



浙公网安备 33010602011771号