spring源码,个人理解

从一个小例子说一下spring中bean的创建流程

示例:A依赖B; B依赖A

@Component
public class A {
    @Autowired
    private B b;
}
@Component
public class B {
    @Autowired
    private A a;
}

在这里插入图片描述
上面演示的例子就是循环注入

如果改为多例的化,运行时就会报错,循环引用异常,找不到对象

@Scope(“prototype”)
在这里插入图片描述
Spring中的循环依赖问题在单例的情况下,Spring是已经帮我们解决好了,多例没有解决循环依赖问题。

为啥,多例的情况下 Spring没有去解决循环依赖问题?

因为在多例的情况下,设置的多例的对象没有明确哪一个,就会产生循环依赖问题。

SpringBean循环依赖三级缓存概念

思考问题:单例对象在什么时候创建?

在IOC容器被创建的时候创建

多例的情况下,是在getbean()调用的情况下创建。多例对象每次用完就会去销毁掉。

SpringBean Aservice对象被创建流程步骤源码分析

public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        A bean = context.getBean(A.class);
    }

在这里插入图片描述
35行点进去

       synchronized (this.startupShutdownMonitor) {
			// 容器预先准备,记录容器启动时间和进行标记状态
			prepareRefresh();

			// 创建BeanFactory。如果已经存在该工厂,那么销毁其里面的beans和自行关闭。如果没有,则创建工厂,并且进行装载BeanDefinition
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 配置BeanFactory的上下文,比如classLoader和BeanPostProcessor,注册一些需要解决的依赖和需要忽略的依赖、注册涉及容器系统环境的bean等等。
			prepareBeanFactory(beanFactory);

			try {
				// 模板方法,在BeanDefinition被装载后(所有BeanDefinition被加载,但是没有bean被实例化),提供一个修改beanFactory容器的入口。
				postProcessBeanFactory(beanFactory);

				// 在Bean未开始实例之前,提供BeanDefinition修改或者注册的入口。我们熟悉的PropertyPlaceHolderConfigurer就是在这里调用的。
				invokeBeanFactoryPostProcessors(beanFactory);

				//用于拦截Bean创建的BeanPostProcessor。
				registerBeanPostProcessors(beanFactory);

				// 初始化容器所需要的MessageSource,用于国际化处理
				initMessageSource();

				// 初始化容器的事件广播器。
				initApplicationEventMulticaster();

				// 模板方法
				onRefresh();

				// 注册监听器
				registerListeners();

				// 完成容器的初始化,里面会调用preInstantiateSingletons()完成单例对象的创建。
				finishBeanFactoryInitialization(beanFactory);

				// 完成上下文的刷新工作
				finishRefresh();
			}

AbstractApplicationContext类
这里重点介绍finishBeanFactoryInitialization方法,878行点进去
在这里插入图片描述

DefaultListableBeanFactory类

获取bean,882行点进去
在这里插入图片描述

AbstractBeanFactory类

202行点进去
在这里插入图片描述

AbstractBeanFactory类

在这里插入图片描述在这里插入图片描述
这里说一下第一次调用这个方法时,取到的对象都是空的,直接返回。
第二次调用时在看这吧,要不然会弄晕
第二次调用时会先从一级缓存获取bean获取,没取到,
判断这个bean是不是正在创建中(getSingleton的重载方法处理过了,后面会说),是的话从二级缓存中去取,取不到的话判断是否允许循环依赖,允许的话,会去三级缓存中去获取。取到了返回这个bean,

现在返回到调用这个方法的类里面(AbstractBeanFactory.java)

326行点进去
在这里插入图片描述
这个getSingleton重载方法大家可以点进去,看到有个beforeSingletonCreation(beanName)方法,这个方法的作用就是
将bean加进singletonsCurrentlyInCreation(set集合),标记这个bean正在创建中

329行点进去

AbstractAutowireCapableBeanFactory类

518行点进去
在这里插入图片描述

AbstractAutowireCapableBeanFactory类

在这里插入图片描述
600行是对象进行属性赋值的地方。先看前面585行的addSingletonFactory方法
在这里插入图片描述
addSingletonFactory方法很有用,点进去

DefaultSingletonBeanRegistry类

在这里插入图片描述
这里记录一下,循环依赖时,创建A对象时先将自己曝光出去,先放进三级缓存(addSingletonFactory方法),同时删除二级缓存,在populateBean方法中会发现引用了B对象,然后创建B对象,B对象执行创建流程,B对象发现自己依赖A对象,又会去执行创建A对象的流程,这里就会第二次执行getSingleton方法了,在这个方法里肯定能找到
在三级缓存中的A对象(此时A对象还没有进行属性赋值,是个不完全的对象),然后将三级缓存对象赋值给一级缓存并放进二级缓存中,同时删除三级缓存中的A对象,然后将A对象注入自己,并走完后面的创建bean的流程,这时B对象已经是一个完全的对象了,回到A对象的populateBean的方法中(这时候B对象创建完成注入到A对象中),A对象此时还没有执行完populateBean方法,A对象执行属性赋值以及后面的初始化动作(个人理解)

AbstractAutowireCapableBeanFactory类

执行完600行的populateBean方法(这里就是上面说的,进行属性赋值),然后执行601行的initializeBean方法
在这里插入图片描述
总结一下bean的创建流程,创建bean时,先从缓存中找,有就返回这个bean,没有就创建用BeanWrapper包装一下(初始化但还没有值),
然后populateBean方法进行属性赋值,initializeBean方法执行对象初始化前的一些操作,先判断这个bean有没有实现某个Aware,将Aware放进去,Aware主要作用是将bean跟spring容器联系起来,要不然老认为Aware是无意识的,然后执行这个bean的前置处理器,如果实现了InitializingBean接口在这里调用一下,执行这个bean的后置处理器,
然后放到单例缓存池中,后面会执行这个bean的销毁方法…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值