前置准备
首先,准备一点必要的代码:
- 定义ServiceA类:
@Service
public class ServiceA {
}
- 定义MyConfig类, 用于Spring能扫描到ServiceA类
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(value = "com.dcj.spring.circulardependency")
public class MyConfig {
}
- 定义Test类
public class Mytest {
public static void main(String[] args) {
// 通过MyConfig配置类,扫描对应包的类
AnnotationConfigApplicationContext applicationContext
= new AnnotationConfigApplicationContext(MyConfig.class);
ServiceA serviceA = applicationContext.getBean(ServiceA.class);
}
}
执行流程
- 从
new AnnotationConfigApplicationContext(MyConfig.class)
开始
说明: refresh()方法其实是父类AbstractApplicationContext.refresh()
方法。
- 进入
AbstractApplicationContext.finishBeanFactoryInitialization()
方法,在此方法中,完成单例bean的实例化。
- 进入
beanFactory.preInstantiateSingletons()
方法,此方法定义为:确定所有非懒加载的单例bean能够被实例化。
备注:preInstantiateSingletons
方法是ConfigurableListableBeanFactory
接口中定义, 由DefaultListableBeanFactory
类实现。
- 进入
AbstractBeanFactory.getBean(name)
方法。
- 进入
AbstractBeanFactory.doGetBean(...)
方法,此方法逻辑很关键。也是代码重点解读的部分。
doGetBean
核心逻辑:
Object sharedInstance = getSingleton(beanName)
先依次尝试从一级缓存、二级缓存、三级缓存中拿bean实例。特别说明的是:如果一级缓存、二级缓存不存在,但是三级缓存存在的话,则从三级缓存中拿bean, 此时本质执行的是getEarlyReference
方法,拿到后,将三级缓存中拿到的bean上移到二级缓存。- 如果步骤1没返回,就执行
getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法。此方法大致分为如下几步:
- 2.1: 标记当前bean正在创建中,其实就是往
singletonsCurrentlyInCreation
集合中设置当前beanName - 2.2: 执行
singletonObject = singletonFactory.getObject();
方法,其实等价于执行createBean(beanName, mbd, args)
方法
- 2.2.1 创建出原始bean, 也就是instanceWrapper
- 2.2.2 将当前bean的ObjectFactory实例,添加到三级缓存,仅仅是添加进去,三级缓存的方法并未执行
- 2.2.3 填充原始bean的属性
- 2.2.4 初始化原始bean
- 2.2.4.1 执行aware方法
- 执行bean的后置处理器逻辑
- 执行初始化方法
- 执行bean的后置处理器逻辑
- 2.2.5 返回真正可以使用的bean
- 2.3:清除
singletonsCurrentlyInCreation
标记,表示当前bean已创建完成 - 2.4:清空对应bean的三级缓存,清空对应bean的二级缓存,并将其放入一级缓存
也就是说:DefaultSingletonBeanRegistry.getSingleton(beanName, singletonFactory)
这个方法返回的,是已经可以直接拿来用的bean。
此时上面的步骤2.2再细分,createBean(beanName, mbd, args)
做了如下几件事:
一些结论
- 任何一个单例bean, 首先对应的ObjectFactory实例, 一定会被加入到三级缓存。
- 该bean只有被循环依赖时,三级缓存的
getEarlyBeanReference
方法才会被执行,它返回真实bean或者对应代理bean(有AOP时); - 只有被循环依赖时,bean才会进入二级缓存,否则没机会进二级缓存
- 如果bean没有被循环依赖, 但是有AOP代理, 代理bean是通过后置处理器的逻辑产生的。