1. 普通java对象创建过程
举例:BusinessService businessService=new BusinessService();
编译:将.java文件编译成class文件
加载:等到类需要被初始化时(比如new) class文件被虚拟机通过类加载器加载到jvm(类加载过程参考https://www.cnblogs.com/enhance/p/10986340.html)
初始化:初始化阶段为类变量赋值为代码期望的值,供我们使用
简单来说,普通java环境创建对象是用Class对象作为模板进来创造出具体的实例
2. Spring管理Bean实例化过程
2.1 Spring bean 元信息(beanDefinition)读取阶段。
Spring启动时,spring按照声明bean方式(比如xml生命bean,又比如使用@Configuration @Bean @Service等注解声明bean等)去读取声明的信息
2.2 spring bean 注册阶段
这些信息被封装成BeanDefination,最后把这些信息收集到beanDefinationMap中。至此spring声明的bean已经注册到ioc容器
——>遍历beanDefinationMap,执行BeanFactoryPostProcessor这个bean工厂后置处理逻辑,可以对bean元数据(@Scope @Lazy @DependsOn等)进行修改(比如@DependsOn会优先实例化其修饰的方法)
2.3 spring bean实例化阶段
实例化对象(只是把对象创建出来,但对象属性还没有注入,比如UserService依赖SendService,在这一步UserSerice中以来的SendService还是null)
——>把对象属性注入(比如@Autowired注解的生效就是这个阶段)
2.4 注入Aware接口
属性注入到对应bean后,判断该bean是否实现了Aware相关接口(比如
@Service public class DemoService implements BeanNameAware, BeanClassLoaderAware { private String beanName; private String classLoader; @Override public void setBeanName(String name) { beanName = name; } public String getBeanName() { return beanName; } @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader.toString(); } public String getClassLoader() { return classLoader; } }View Code
Aware类型接口的作用就是让我们能拿到spring容器中的一些资源,Aware之前的名字就是可以拿到的资源,比如BeanNameAware可以拿到BeanName)
2.5 BeanPostProcessor
上边步骤bean对象已经被正确构造,但如果想要对象被使用前再进行一些自定义的处理,就可以通过beanpostprocessor接口实现。
BeanPostProcessor接口提供两个函数:postProcessBeforeInitialzation:这个函数先于InitialzationBean执行,称为前置处理
postProcessAfterInitialzation:这个函数在InitialzationBean之后执行,称为后置处理
——>before方法执行完,则执行init相关方法比如@PostConstruct、实现了InitializingBean接口、init-method方法
——>执行BeanpostProcessor的after方法
——>基本流程走完后,可以获取到对象去使用
2.6 DisposableBean和destroy-method
好init-method一样,通过给destroy-method指定函数就可以在bean销毁前执行指定的逻辑
3.三级缓存解决循环依赖问题
a)假设先创建Aservice的bean。在bean实例化阶段,先创建出Aservice的bean,创建出Asercvice的对象后就创建Aservice对应的ObjectFactory放到三级缓存。
b) 然后Aservice继续往下走,到了注入属性Bsercice阶段,开始处理@Autowired要注入Bservice对象,此时会从一级缓存到三级缓存开始依次查找有没有Bservice对应的bean,此时肯定是没有Bservice的。
c) 此时Aservice的注入Bservice过程暂停,现在去创建Bservice,只有Bservice创建完后才能注入给Aservice
d) 于是Bservice开始创建,先实例化一个Bservice对象然后缓存到对应的一个ObjectFactory到第三季缓存,然后就到需要处理@Autowird注解注入Aservice时候,此时先去一级缓存找Aservice没有,再去二级缓存也没有Aservice,直到三级缓存找到Aservice,这样就拿到早起的Aservice对象。然后将早期的AService对象放到二级缓存,为什么需要放到二级缓存,主要是怕还有其他的循环依赖,如果还有的话,直接从二级缓存中就能拿到早期的AService对象。
e) 虽然Bservice注入的是早期的Aservice对象(仅仅是因为早期的Aservice对象可能有些bean创建的步骤没有完成),但跟最后完全创建好的Aservice bean是同一个对象
f) 此时Bservice中@Autowired Aservice步骤完成,经过其他springbean创建步骤后Bservice完全创建完成
g) Bservice创建完成后,将Bservice放到一级缓存,然后清空二三级缓存
h) 此时Aservice继续之前暂停@Autowired Bservice步骤。
i) 这样Bservice创建过程中注入早起三级缓存中Aservice,然后在Aservice注入一级缓存中Bservice。就这样解决循环依赖问题
参考文献
https://www.zhihu.com/question/38597960
https://jishuin.proginn.com/p/763bfbd750e7
https://www.zhihu.com/question/38597960/answer/2336854085
https://zhuanlan.zhihu.com/p/518361118
标签:生命周期,Bservice,对象,spring,Aservice,bean,Bean,缓存,创建 From: https://www.cnblogs.com/enhance/p/17024932.html