SpringBean生命周期
2021-10-18 21:13:27 0 举报
SpringBean生命周期以及循环依赖处理原理、循环依赖面试题
作者其他创作
大纲/内容
知识完成堆空间的开辟,并没有设置属性值
实例化Bean
bean的定义信息
实例化和初始化分开处理提前暴露对象
基本使用context.getBean
context = new ClassPathXmlApplicationContext();context.getBean(Person.class);
Ba
半成品:只完成实例化,未完成初始化的对象
工厂模式
spring处理的核心逻辑
对源码有兴趣的都是BT----->主要为了钱
init-method方法
BeanFactoryPostProcessor
后置处理器
抽象定义规范接口
1、不要忽略源码中的注释2、千万不要一开始的时候就深入细节,死扣某一个方法,先梳理脉络,然后看细节(总-分-总流程)3、大胆猜测,大胆验证,8分靠猜4、见名知义5、坚持6、坚持7、坚持
BeanPostProcessor.postProcessAfterInitialization
给对象来进行基本的赋值操作
doCreateBean
动态代理
refresh()
在堆中开辟一块空间,属性都是默认值
BeanPostProcessor.postProcessBeforeInitialization
当应用正在一个application context运行时
DestructionAwareBeanPostProcessors's postProcessBeforeDestruction
createBean
BeanNameAware's setBeanName
ApplicationEventPublisherAware's setApplicationEventPublisher
完整表述SpringBean的生命周期
加载
map
存放
代理对象
初始化
BeanFactory
如果想在spring不同的生命周期阶段做不同的处理工作,我应该怎么办?观察者模式:监听器、监听事件、多播器
SpringBean生命周期-基于BeanFactory源码注释
半成品
IOC容器
bean的生命周期
有了当前对象,再设置值,相当于分2个步骤
关闭Bean工厂
A
doGetBean
aware接口存在的意义是:方便通过spring中的bean对象获取对应容器中的相关属性值
postProcessBeforeInitialization
postProcessAfterInitialization
完整对象
IOC
https://www.bilibili.com/video/BV1iZ4y137CZ?p=19&spm_id_from=pageDriver1、三级缓存解决循环依赖问题的关键是什么?为什么通过提前暴露对象能解决?因为实例化和初始化分开操作,在中间过程中给其他对象赋值的时候,并不是一个完整对象,而是把半成品对象赋值给了其他对象。2、如果只使用一级缓存能否解决循环依赖?不能。在整个处理过程中,缓存中放的是半成品和成品对象,如果只有一级缓存,那么成品和半成品都会放到一级缓存中,有可能在获取过程中获取到半成品对象,此时半成品对象是无法使用的,不能直接进行相关的处理,因此要把半成品和成品的存放空间分割开来。3、如果只使用二级缓存行不行?为什么需要三级缓存?如果能保证所有的bean对象都不去调用getEarlyBeanReference此方法,使用二级缓存可以吗?可以。如果保证所有的bean对象都不调用此方法,就可以只用二级缓存!使用三级缓存的本质是解决AOP代理问题!!!4、在创建代理对象的时候,如果某个bean需要代理对象,那么会不会创建普通的bean对象?会,一定会。5、为什么使用三级缓存可以解决这个问题?当一个对象需要被代理的时候,在整个创建过程中是包含两个对象。一个是普通对象,一个是代理生成的对象。bean默认都是单例,那么在整个生命周期的处理环节中,一个beanname能对应2个对象吗?不能,既然不能的话,保证在使用的时候加一层判断,判断一下是否需要进行代理的处理。6、我怎么知道你什么时候使用呢?因为不知道什么时候回调用,所以通过一个匿名内部类的方式,在使用的时候直接堆普通对象进行覆盖操作,保证全局唯一!
Spring
BeanFactoryPostProcessor比如对配置中占位符的替换处理
创建对象和设置值合在一起,导致不能解决循环依赖
初始化B
有
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessorBeanPostProcessor的子接口,用于添加销毁前回调。典型用法是在特定的bean类型上调用自定义销毁回调方法,匹配相应的初始化回调。
k:av:A@1755成品
k:av:A@1755半成品
自定义destroy-method
使用
给属性赋值
bean
执行初始化方法
getBean
直接赋值返回
存放成品对象
populateBean
k:bv:B@2152成品
填充属性
为所欲为
B
ObjectFactory是一个函数式接口,仅有一个方法,可以传入lambda表达式,可以是匿名内部类,通过调用getObject方法来执行具体的逻辑
EnvironmentAware's setEnvironment
Environment
三级缓存
构造方法
Constructor ctor = clazz.getDeclaredConstructor();Object ob = ctor.newInstance();
APO
去容器中查找
k:bv:lambda
直接赋值成功
spring容器中有无a对象
cglib
接口将由需要一次对其所有属性已由BeanFactory设置:例如,执行自定义初始化,或仅检查是否已设置所有强制属性。实现InitializingBean的另一种方法是指定自定义init方法,例如在xmlbean定义中。
set
先实例化A
BeanDefinitionReader
13个方法
没有办法解决循环依赖
Spring在创建对象之前每次都是先从容器中查找,找不到再创建
注解
BeanFactoryAware's setBeanFactory
开始完成bean的创建过程了
存放半成品对象
增强器
要由想要释放资源的bean实现的接口关于毁灭。BeanFactory应该调用destroy方法,如果它处理缓存的单例。应用程序上下文应该把所有的单例都处理掉。实现自定义DisposableBean的替代方法是自定义destroy-method,例如在xmlbean定义中。有关所有bean生命周期方法的列表,请参见{@link BeanFactory BeanFactory javadocs}。
ApplicationContextAware's setApplicationContext
ResourceLoaderAware's setResourceLoader
存放lambda表达式,来完成代理对象的覆盖过程
单例
反射
实现了BeanPostProcessor接口的后置处理器类(官方的或者自定义的)
容器
B@2152
MessageSourceAware's setMessageSource
finishBeanFactoryInitialization(beanFactory);beanFactory.preInstantiateSingletons();
执行aware接口需要实现的方法
k:av:lambda
如何创建Bean对象
否
Ab
一级缓存
Class clazz = Class.forName();Class clazz = 类名.class;Class clazz = 对象名.getClass();----------Constructor ctor = clazz.getDeclareConstructor();Object ob = ctor.newInstance();
基石
A@1755
数据结构
创建实例
实例化
System.getProperties()
spring默认scope是单例的
BeanPostProcessor后置处理器增强器
从缓存中查找对象时,先查一级缓存,再查二级缓存,再查三级缓存
BeanPostProcessor:允许自定义修改新bean实例的工厂钩子,e、 g.检查标记接口或用代理包装它们。ApplicationContexts可以自动检测其应用程序中的BeanPostProcessor beanbean定义并将它们应用于随后创建的任何bean。普通bean工厂允许后处理器的程序注册,应用于通过此工厂创建的所有bean。通常,通过标记接口填充bean的后处理器或者类似的将实现{@link#postprocessabeforeignization},而用代理封装bean的后处理器通常实现{@link#postProcessAfterInitialization}。ApplicationContext自动检测通过BeanPostProcessor接口的实现定义的任何bean,并将这些bean注册为后处理器,然后在创建bean时由容器适当地调用。
jdk
InitializingBean's afterPropertiesSet
二级缓存
初始化操作自定义的init-method
Spinrg源码架构设计
ServletContextAware's setServletContext
此时要给B对象的a属性赋值,要去spring容器中查找a对象
spring是个框架生态springbootspringcloud扩展性
可以解决循环依赖
完成b对象的实例化
DisposableBean's destroy
此时要给b属性赋值,b是一个完全独立的对象,所以此时要去spring容器中查找b对象
BeanDefinitionBean定义信息
xml
初始化A
进行扩展实现
判断是否有b对象
BeanClassLoaderAware's setBeanClassLoader
应用程序运行期间,能否当前系统的环境变量或者系统属性
半成品(只完成实例化,未完成初始化)
调用init-method方法完成
list
解析
调用set方法完成
销毁流程
aop
EmbeddedValueResolverAware's setEmbeddedValueResolver
System.getEnv()
循环依赖
new
是
在堆中开辟了一块空间
PostProcessor
销毁
XML<bean id=? class=?><property name=? value=?><property name=? ref=?></bean><bean id=? class=?><constructor-arg name=? value=?><constructor-arg name=? ref=?></bean>
收藏
0 条评论
下一页