Spring的初始化流程以及循环依赖原因和解决方法

Spring的初始化过程

容器先初始化 就是调用复合方法refresh bean的生命周期是在refresh方法里面的 这个refresh方法里面和bean生命周期关系最大的两个方法是 registerBeanPostProcessors(beanFactory);
finishBeanFactoryInitialization(beanFactory) :这个方法将会对非延迟加载的单例Bean进行预实例化
他们都调用的getBean->doGetBean

bean的生命周期:spring先将打了@service这种注解的bean解析成BeanDefinition,并以beanName为key BeanDefinition为value存在concurrentHashMap里面 并且把bean再存在一个list里面 遍历这个list进行bean的实例化

bean的实例化就是先调用构造方法 然后通过beanwrapper进行依赖注入 然后看看有没有aware接口init-method什么的 也就是bean的生命周期的前面的几个过程
实例化完了就放在一级缓存里面

这个依赖注入是在getBean方法里面完成的。这个getBean实际上是AbstractBeanFactory的getBean

getBean(1.创建一个新的bean 2.从缓存里面拿bean)—>doGetBean–>getSingleton【这个方法就是尝试去三级缓存里面拿bean】–>getSingleton(a,()->{})【这是一个重载方法 作用就是创建bean创建完了就放进三级缓存 包括实例化/属性注入/初始化】-
在这里插入图片描述
上面这张图是创建bean的 也就是getSingleton的重载方法
如果不是延迟加载 ioc容器初始化的时候也会调用这个getBean 进行提前依赖注入 预实例化

如果延迟加载 那么就先初始化ioc 然后到了getBean这一步的时候 再来初始化bean

Bean的生命周期

1.实例化Bean:
IOC容器通过获取BeanDefination对象的信息进行实例化,实例化对象被包装在BeanWrapper(Bean的包装)对象中
2.设置对象的属性(DI依赖注入):getbean方法 --> createBean–>createBean里面的populateBean
真正执行依赖注入的就是populateBean()方法 就一行代码
但是这个方法最终调用的是beanwrapper接口的setPropertyValues方法 完成属性的注入
3.注入Aware接口():Spring会检测该对象是否实现了xxxAware()接口,并将相关的xxxAware实例注册给bean
【Aware接口就是增强bean的感知 接口里面啥也没有 但是BeanNameAware接口 继承Aware接口 然后有个setBeanName方法
如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;
如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来】
4.BeanPostProcessor:自定义的处理(分为前置处理和后置处理)

5.InitializingBean 和 init-method:执行我们自己定义的初始化方法,也就是说是afterPropertiesSet()方法里面的内容 init-method是属性

6.使用
7.destory:bean的销毁 当然对应的肯定有DisposableBean接口和destroy-method属性

循环依赖

是什么?

就像controller依赖service service依赖dao一样
A依赖B B依赖C C依赖A
能解决的前置条件:
1.出现循环依赖的bean必须是单例
2.依赖注入的方式不能全是构造器注入
全是setter注入肯定没问题了能解决
setter+构造器注入也行好像还能搏一搏
如果是构造器注入呢 怎么办?
@lazy注解 让spring懒加载 当真正用到的时候 再去加载

对象实例化分为三步:
1.createBeanInstance():调用对象的构造方法实例化
2.populateBean() :属性填充
3.initializeBean() :调用spring xml中的init方法初始化

三级:singletonFactories : 早期曝光对象工厂
二级:earlySingletonObjects :早期曝光对象
一级:singletonObjects:单例池
怎么解决的?
通过三级缓存 我们创建对象分为三步 先调用构造函数实例化 然后属性填充 再初始化 允许调用构造函数之后 即使属性未填充 可以通过三级缓存提前暴露 就是把bean包装成一个工厂放进三级缓存 如果A被AOP代理,那么通过这个工厂获取到的就是A代理后的对象,如果A没有被AOP代理,那么这个工厂获取到的就是A实例化的对象。
创建bean的时候Spring先从一级缓存中获取 获取不到就去二级缓存里面找 如果还找不到就去三级缓存通过singletionFactory.getObject()方法获取 如果获取到了就放进二级缓存里面

为什么要使用三级缓存呢?二级不可以吗?
如果用二级缓存 意味着Bean在实例化之后就完成AOP代理 但是Spring的设计原则是在Bean生命周期的最后一步完成AOP代理

所以spring解决循环依赖的关键就在于这个三级缓存 而加入三级缓存的前提是执行了构造器 所以纯构造器的循环依赖没办法解决
(可以通过@lazy注解延迟加载)

将bean包装成一个工厂 添加进了三级缓存

举例子:
比如A依赖了B B依赖了A A先进行初始化 刚完成第一步执行完构造方法 发现自己依赖B 就尝试去get(B) 但是这个时候B还没有呗创建出来 (这个时候已经暴露了)于是创建B B在初始化第一步的时候发现自己依赖A 然后去一级缓存里面找A 找不到 二级缓存 找不到 三级缓存 由于A将自己提前暴露了 所以B能拿到A 然后B就完成了初始化 把自己放进了一级缓存里面 然后A也完成了初始化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值