生命周期,就是从诞生到死亡的一个过程。Spring 中 bean 也是如此。在 Spring 中的 ConfigurableApplicationContext 的 refresh 开始直到一个 bean 可以被正常使用,中间经历了一系列初始化操作;而在其 close 后又经历了一系列销毁操作,这被称之为 Spring 中 bean 的生命周期。
周期
Spring 中的 bean 经历了以下阶段:
其中红色的框不属于 Spring 来管理了。
实例化
实例化就是 Spring 通过反射来调用构造方法来实例化一个对象。
初始化
Spring 的初始化有两种方式,一种是实现 InitializingBean
接口,另一种是在一个方法上面加上 @PostConstruct
注解表示这是一个初始化方法。
销毁
Spring 的销毁对象的方式也有两种,一种是实现 DisposableBean
,另一种是在一个方法上加 @PreDestroy
注解;和 初始化 的两种方式相对应。
顺序
具体顺序是如何,我们用一段代码就可以看到。
// NormalEntity.java 这是一个将往 Spring 中注入的类
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class NormalEntity implements InitializingBean, DisposableBean {
public NormalEntity() {
System.out.println("NormalEntity constructor...");
}
@PostConstruct
public void init() {
System.out.println("NormalEntity PostConstruct");
}
@PreDestroy
public void preDestroy() {
System.out.println("NormalEntity preDestroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("NormalEntity afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("NormalEntity destroy");
}
}
// MainConfig.java
import org.springframework.context.annotation.Bean;
public class MainConfig {
@Bean
public NormalEntity normalEntity() {
return new NormalEntity();
}
}
// MainTest.java 这里是启动类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
NormalEntity bean = applicationContext.getBean(NormalEntity.class);
System.out.println(bean);
// 这里使用的是 AnnotationConfigApplicationContext,需要手动调用 close
// 如果是 SpringBoot 项目,会自动注册 shutdown hook,里面调用了 close 方法
applicationContext.close();
}
}
会看到控制台打印出了结果,也展示了调用顺序:
NormalEntity constructor...
NormalEntity PostConstruct
NormalEntity afterPropertiesSet
NormalEntity preDestroy
NormalEntity destroy
代码的调用
在构造方法下一个断点,就可以根据调用栈知道调用路径了。
下面简要说明几处。
AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory)
在 AbstractApplicationContext#refresh
方法的倒数第二步调用了此方法来实例化容器中所有的非懒加载的bean(懒加载的肯定是用到的时候再实例化),这里就最终可以到AbstractBeanFactory#doGetBean(String, Class<T>, Object[], boolean)
里面的getSingleton(String, ObjectFactory<?>)
,那最终其实就是调用参数ObjectFactory<?>
提供的createBean(String, RootBeanDefinition, Object[])
方法。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])
- 调用
createBeanInstance(String, RootBeanDefinition, Object[])
方法来使用构造方法实例化对象; - 在下面的
applyMergedBeanDefinitionPostProcessors(RootBeanDefinition, Class<?>, String)
中使用BeanPostProcessor
调用有注解的初始化方法; - 在
initializeBean(String, Object, RootBeanDefinition)
方法中调用了实现了InitializingBean
接口的afterPropertiesSet
方法
经历以上三步骤,bean的初始化完成。
同时如果想要知道Spring的bean在销毁时做了什么,可以在另外两个销毁方法下断点,就可以知道了。