本人最近想学习一下spring的源码,无奈spring源码实在是庞大,想要全面学习有点困难,不如逐个点攻破。在网上随便翻面试题的时候偶然看到这个问题,想着就从这开始吧。刚开始学spring的时候,网课上的老师就带着一行一行的往里看,那看的是一个头昏眼花,直犯困。直到现在,看了几年java,想要了解每一行代码都做了什么,还是非常晦涩的,感觉只有去问作者了。我现在也看开了,不再深究每行代码都做了什么,很多方法就看个输入输出,大概知道做了啥事就行了,毕竟也不需要我们写一个spring出来。我感觉spring最厉害的点就在于他的可扩展性,通过各种回调方法,监听器扩展,可以灵活设计各种中间件。spring中的设计模式运用也是相当巧妙,如果对设计模式不够了解的话,想要看懂spring还真是有点难。没办法了,只能硬着头皮上了。
我发现用chatgpt学习源码也挺不错,不过3.5版本的还是有点问题,我发现他喜欢自己编源码,生成源码和实际的总会有点出入。不过我们可以灵活点,抓住某个点问他这行代码做了什么,给个注释啥的。感觉如果gpt4或者5的话应该就是神器了,不过既然ai这么懂源码,还要我们干嘛,哎~~。
spring解决循环依赖老生常谈的话题了,网上资料一大堆,大家都知道是用了三级缓存。一级缓存存储实例化、属性注入、初始化完成的bean,二级缓存存储实例化完成但还没有属性注入的bean,三级缓存存储提前暴露对象ObjectFactory。如果发生循环依赖,某个bean注入依赖的时候,可以调用三级缓存中的ObjectFactory.getObject方法获取实例化完成但是还没有属性注入的半成品bean。
说实话,循环依赖这里很绕,因为这里用了递归。spring在创建一个bean的时候,都会先调用getBean方法,尝试获取一下,如果获取不到就调用createBean方法创建。然后在populateBean属性注入的时候,同样还会调用getBean方法,尝试获取一下,获取不到就创建 。属性注入的时候如果属性类中又有需要依赖注入的bean,还会调用getBean,就这么一直递归下去。递归是要有递归终止条件的,递归的终止条件就是getBean时三级缓存中有值,并调用三级缓存中ObjectFactory的getObject方法拿到了半成品bean。获取到了半成品bean,此时的递归停止,开始返回。
首先先准备测试代码:
@Component
public class Demo1{
@Autowired
private Demo2 demo2;
}
@Component
public class Demo2{
@Autowired
private Demo1 demo1;
}
根据下面的调用链,来到getBean的doGetBean方法中。spring的源码里有个习惯,某项功能的方法,方法名前面加了do才是真正执行逻辑的方法。比如真正获取bean的方法是doGetBean由getBean调用doGetBean;真正创建bean的方法是doCreateBean由createBean方法调用doCreateBean。
SpringApplication#run(TestApplication.class, args) ---->
run(new Class>[] {primarySource}, args) ---->
new SpringApplication(primarySources).run(args) ---->
refreshContext(context) ----> refreshContext(context) ---->
((AbstractApplicationContext) applicationContext).refresh() ---->
finishBeanFactoryInitialization(beanFactory) ---->
beanFactory.preInstantiateSingletions() ---->
DefaultListableBeanFactory#preInstantiateSingletons() ---->
getBean(name) ---->
doGetBean(name, null, null, false)
根据上面的流程,进入AbstractBeanFactory类中的doGetBean方法。注意啊,在我们的示例代码中,Demo1和Demo2相互依赖,所以在debug测试的时候,下面的doGetBean()方法会进入4次,我这里标记一下。我每次只展示会用到的代码,其他代码先省略,下次进来的时候,如果用到了其他代码,会再展示。(我的源码都是粘贴自互联网,里面的注释也是粘贴的)
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 处理别名BeanName、处理带&符的工厂BeanName
final String beanName = transformedBeanName(name);
Object bean;
// 先尝试从缓存中获取Bean实例,这个位置就是三级缓存解决循环依赖的方法
Object sharedInstance = getSingleton(beanName);
// 后面的逻辑先省略,用到的时候再粘贴...
// 返回 Bean
return (T) bean;
}
getSingleton(beanName)方法中可以看到了三个缓存了:
singletonObjects:一级缓存
earlySingletonObjects: 二级缓存
singletonFactories:三级缓存
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1.首先在单例bean集合中检查当前beanName对应的bean是不是已经被创建过了,如果被创建过了直接取出
Object singletonObject = this.singletonObjects.get(beanName);
// 2.如果当前beanName对应的bean还没有被创建过 && 当前的bean是否正在创建(首次false)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = 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);
}
isSingletonCurrentlyInCreation()用来判断当前beanName是否正在创建中。
此时的beanName是demo1,由于demo1还没有被创建为bean,isSingletonCurrentlyInCreation()会返回false,getSingleton()直接返回null。
再次回到doGetBean()方法中。继续向下执行,来到mbd.isSingleton的if代码块中,调用getSingleton()的重载方法。注意,在getSingleton参数中,传入了一个ObjectFactory对象,该对象的getObject方法会调用createBean()方法。说明这次的getSingleton不只是get,还会create。
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 处理别名BeanName、处理带&符的工厂BeanName
final String beanName = transformedBeanName(name);
Object bean;
// 先尝试从缓存中获取Bean实例,这个位置就是三级缓存解决循环依赖的方法
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 1. 如果 sharedInstance 是普通的 Bean 实例,则下面的方法会直接返回
// 2. 如果 sharedInstance 是工厂Bean类型,则需要获取 getObject 方法,可以参考关于 FactoryBean 的实现类
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// ... 省略其他代码
// 创建单例 bean 实例
if (mbd.isSingleton()) {
// 把 beanName 和 new ObjectFactory 匿名内部类传入回调
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 创建 bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 创建失败则销毁
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
// 返回 Bean
return (T) bean;
}
进入到getSingleton()的重载方法中。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// 先尝试从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// ... 省略部分代码
// 将bean添加到singletonsCurrentlyInCreation中,前面的isSingletonCurrentlyInCreation方法就是从这里面操作的集合中检测是否正在创建。
// 由于这个beanName被加入到了singletonsCurrentlyInCreation集合中,所以下次又遇到这个beanName,isSingletonCurrentlyInCreation方法就会返回true。
beforeSingletonCreation(beanName);
// ... 省略部分代码
try {
// 这里调用该方法参数中传入的lambda表达式,执行createBean()方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// 后面的方法先省略 ...
}
}
createBean方法我们就不看了,直接来到doCreateBean方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
// 这里先根据RootBeanDefinition创建一个beanWrapper,根据这个名字可以推断,这是bean的装饰对象。反正这里只是createBean的第一步,将beanDefinition转为BeanWrapper。
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 提前暴露,用于解决循环依赖问题
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// ... 省略部分代码
return exposedObject;
}
addSingletonFactory()中实现了对“demo1”的提前暴露。
看到这里,我们可以总结一下之前的步骤:
进入到addSingletonFactory方法:
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
//如果一级缓存里没有
if (!this.singletonObjects.containsKey(beanName)) {
//放入三级缓存
this.singletonFactories.put(beanName, singletonFactory);
//从二级缓存移除
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
addSingletonFactory做了一个重要的操作,就是将对象提前暴露。
再次回到doCreateBean()中。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
// 这里先根据RootBeanDefinition创建一个beanWrapper,根据这个名字可以推断,这是bean的装饰对象。反正这里只是createBean的第一步,将beanDefinition转为BeanWrapper。
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 提前暴露,用于解决循环依赖问题
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// ... 省略部分代码
return exposedObject;
}
populateBean(beanName, mbd, instanceWrapper)方法实现对“demo1”对象的依赖注入。这行代码里面做的操作很复杂,但是大体就是为bean中标记了@Autowired的变量进行赋值。
Demo1中通过@Autowired注解引入了Demo2,所以通过populateBean方法进行依赖注入的时候,又会调用getBean ----> doGetBean方法尝试获取并创建demo2。
我们再次回到doGetBean()方法中,此时再次进入到getSingleton()中,注意此时getBean的已经不是demo1了,而是它内部的实例变量demo2。由于demo2也是初次创建,所以走到这里和demo1走到这里的流程是一样的。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1.首先在单例bean集合中检查当前beanName对应的bean是不是已经被创建过了,如果被创建过了直接取出
Object singletonObject = this.singletonObjects.get(beanName);
// 2.如果当前beanName对应的bean还没有被创建过 && 当前的bean是否正在创建(首次false)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = 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);
}
由于此刻的demo1和demo2都是spring初次尝试获取并创建,所以第一次demo1进入doGetBean和第二次demo2进入doGetBean的流程都是一样的。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
这里与demo1来到的也没什么两样,直接到doCreateBean()中,再次展示一下doCreateBean()方法。
在执行到populateBean方法之前,demo2也会提前暴露,生成ObjectFactory对象放入到三级缓存中。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
// 这里先根据RootBeanDefinition创建一个beanWrapper,根据这个名字可以推断,这是bean的装饰对象。反正这里只是createBean的第一步,将beanDefinition转为BeanWrapper。
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 提前暴露,用于解决循环依赖问题
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// ... 省略部分代码
return exposedObject;
}
由于demo2中通过@Autowired注解引入了demo1,所以在populateBean()方法中,会通过getBean()方法尝试获取demo1的bean。所以,下面就是第三次进入doGetBean()方法
这次是在处理demo2的依赖注入问题时需要获取demo1的bean调用的doGetBean方法。此时的getSingleton方法已有不同。因为isSingletonCurrentlyInCreation不再返回false,而是返回true了。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1.首先在单例bean集合中检查当前beanName对应的bean是不是已经被创建过了,如果被创建过了直接取出
Object singletonObject = this.singletonObjects.get(beanName);
// 2.如果当前beanName对应的bean还没有被创建过 && 当前的bean是否正在创建(首次本次为true)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 检查二级缓存中是否有该beanName,有就直接返回,第一还没有,当前Demo1的beanName只是提前暴露,放到了三级缓存中
singletonObject = this.earlySingletonObjects.get(beanName);
// 二级缓存中没有
if (singletonObject == null && allowEarlyReference) {
// 二级缓存中没有且允许循环依赖,则检查三级缓存中是否存在当前beanName(Demo1存在)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用提前暴露的Demo1的ObjectFactory对象的getObject方法
singletonObject = singletonFactory.getObject();
// 调用三级缓存中存储的Demo1的ObjectFactory对象的getObject方法,拿到了Demo1的实例化对象
// 不过此时Demo1实例化对象中的Demo2属性还是为null
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
由于demo1此时在doGetBean的getSingleton方法中返回了不为null的对象,就不会再走createBean了。
那么这时,第二轮中,Demo2的populateBean方法已经执行成功了,Demo2已经依赖注入完成,拿到了demo1。第二轮的createBean方法完成,退出后回到第二轮的doGetBean的getSingleton方法中。createBean是在getSingleton的singletonFactory.getObject()方法中被回调了,继续往后看到addSingleton方法。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 因为创建过程中需要操作 singletonObjects。所以需要加锁
synchronized (this.singletonObjects) {
// 再次尝试获取bean,判断bean是否已经加载。如果加载直接返回。
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// ...
// 做一些bean创建前的准备工作: 记录beanName 正在加载的状态(添加到 singletonsCurrentlyInCreation 缓存中),若bean已经正在加载,则抛出异常。为了解决循环引用的问题
beforeSingletonCreation(beanName);
// ...
try {
// 通过回调方式获取bean实例。
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// ...
if (newSingleton) {
// 加入到缓存中,并删除加载bean过程中所记录的各种辅助状态
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
...
// 主要还是对几个缓存map的操作
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
demo2的bean已经完成创建成功了,所以第一轮中demo1的poplulateBean()调用的getBean()返回了demo2的成品bean。demo1的populateBean调用结束,依赖注入完成,完成初始化方法后,demo1的bean也完成了创建。
结束。