1. 普通java对象创建过程
举例:BusinessService businessService=new BusinessService();
编译:将.java文件编译成class文件
加载:等到类需要被初始化时(比如new) class文件被虚拟机通过类加载器加载到jvm(类加载过程参考https://www.cnblogs.com/enhance/p/10986340.html)
初始化:初始化阶段为类变量赋值为代码期望的值,供我们使用
简单来说,普通java环境创建对象是用Class对象作为模板进来创造出具体的实例

2. Spring管理Bean实例化过程
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 实例化阶段 instanceWrapper = this.createBeanInstance(beanName, mbd, args); } ... Object exposedObject = bean; try { // 属性赋值阶段 this.populateBean(beanName, mbd, instanceWrapper); // 初始化阶段 exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { ... } ... }
如上图所示,spring bean的生命周期可以分为:实例化-》属性注入-》初始化-》使用-》销毁5个阶段.
2.1实例化:
调用createBeanInstance()方法,Spring IOC容器读取元数据(bean的作用域)创建bean实例。但此时bean成员变量尚未初始化,仅完成内存空间分配和构造器执行
2.2属性赋值:
populateBean();为bean内注入依赖的属性,比如使用@Autowired @Resource @Value等注解
三级缓存解决循环依赖就是发生在这一阶段
// DefaultSingletonBeanRegistry.java protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 检查一级缓存(完整Bean) Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 检查二级缓存(早期引用) singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 检查三级缓存(ObjectFactory) ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
2.3初始化:
此阶段执行一些初始化方法:init-method @PostConstruct 或者通过实现InitializingBean接口的afterPropertiesSet()
2.3.1判断是否实现Aware相关接口,
Aware接口是一种标记接口,自定义bean通过实现不同Aware接口,可以向bean中注入ApplicationContext, ClassLoader,beanFactory等对象从而获取对应spring容器资源
Aware接口使用场景 参考https://blog.csdn.net/qusikao/article/details/136631127
- 依赖注入:普通的依赖注入无法获取beanName,AppliationContext,BeanFactory,这时需要让bean实现对应aware接口
- 环境感知:bean在不同环境可能做不同处理,此时bean implement EnvironmentAware,bean便可访问当前Environment根据环境感知操作
- 资源访问:除了基本的依赖注入和环境感知外,
Aware接口还可以用于访问Spring容器中的其他资源。例如,通过实现ResourceLoaderAware接口,Bean可以获得一个ResourceLoader的引用,用于加载类路径下的资源文件
Aware相关接口:
- BeanNameAware: 实现此接口的bean可以获得其在Spring容器中的名称,当bean被创建并添加到容器中时,Spring会调用setBeanName(String name)方法。
- BeanFactoryAware: 实现此接口的bean可以获得对其所在的BeanFactory的引用,这允许bean直接访问容器以查找或操作其他bean,通过setBeanFactory(BeanFactory beanFactory)方法注入。
- ApplicationContextAware: 与BeanFactoryAware类似,但是提供对更高级的ApplicationContext的访问,实现此接口的bean可以通过setApplicationContext(ApplicationContext context)方法获得ApplicationContext的引用。
- MessageSourceAware: 实现此接口的bean可以获得对MessageSource的引用,这允许bean进行国际化消息的处理,通过setMessageSource(MessageSource messageSource)方法注入。
- ApplicationEventPublisherAware: 实现此接口的bean可以获得一个ApplicationEventPublisher的引用,用于发布应用事件,Spring会在适当时刻调用setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)方法。
- ResourceLoaderAware: 实现此接口的bean可以获得对ResourceLoader的引用,这使得bean可以加载资源,如配置文件等,通过setResourceLoader(ResourceLoader resourceLoader)方法注入。
- EnvironmentAware: 实现此接口的bean可以获得对当前应用环境的Environment对象的引用。这允许bean查询配置的属性、配置文件等,通过setEnvironment(Environment environment)方法注入。
- EmbeddedValueResolverAware: 实现此接口的bean可以获得对字符串值解析器的引用,该解析器能够处理占位符(如${...}),通过setEmbeddedValueResolver(StringValueResolver resolver)方法注入。
- SchedulingConfigurerAware (不直接属于Aware接口系列, 但类似): 允许配置计划任务,在Spring Boot应用中,可以通过实现SchedulingConfigurer接口和覆盖configureTasks(ScheduledTaskRegistrar taskRegistrar)方法来定义计划任务
2.3.2 初始化前 beanPostBeforeInitialization()
允许用户在初始化前对bean进行处理,如下图MyBeanPostProcess类实现BeanPostProcessor接口,在类中重写postProcessorBeforeInitilization()

2.3.3 初始化
调用@PostConstruct,实现InitializingBean的afterPropertiesSet()和init-method这三种不同的初始化方法,其运行顺序也是按照前边排序依次进行的
import org.springframework.beans.factory.InitializingBean; import javax.annotation.PostConstruct; public class Foo implements InitializingBean { public void init(){ System.out.println("执行了init生命周期的初始化回调"); } @PostConstruct public void postConstruct(){ System.out.println("执行了postConstruct生命周期的初始化回调"); } @Override public void afterPropertiesSet() { System.out.println("执行了afterPropertiesSet生命周期的初始化回调"); } } import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class InitConfiguration { @Bean(initMethod = "init") public Foo getInitMethodBean() { return new Foo(); } }
其执行结果为
执行了postConstruct生命周期的初始化回调
执行了afterPropertiesSet生命周期的初始化回调
执行了init生命周期的初始化回调
2.3.4 初始化后
在初始化方法后,用户对bean进行处理,如2.3.2中postProcessorAfterInitialization()
2.4 bean使用
2.5 销毁
bean 实现DisposableBean,重写destroy()方法
BeanPostProcessor接口函数

通过自定义这些方法,开发者可以实现:
- 动态代理(如AOP)
- 属性值的动态修改(如加密字段解密)
- Bean的延迟初始化(如
@Lazy注解的支持) - 资源的预释放(如销毁前的缓存清理)
详细版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。就这样解决循环依赖问题
一级缓存:存储已经完成实例化、属性注入和初始化后的bean
二级缓存:存储实例化完成的bean,此时属性并没有注入
三级缓存:存储bean的工厂对象
参考文献
https://blog.csdn.net/qq_15037231/article/details/105938673
https://blog.csdn.net/fox9916/article/details/128522598
https://blog.csdn.net/fox9916/article/details/128522598

浙公网安备 33010602011771号