注:这里说的 Spring Bean 的生命周期指的是 singleton bean。
singleton单例组件,在容器初始化时开始生命周期;
prototype组件,在获得组件的时候才开始生命周期。
对于 prototype 的 bean ,Spring 在创建好交给使用者之后则不会再管理后续的生命周期,所以IOC容器不会调用销毁方法。
4 个阶段:
实例化(Instantiation)
属性赋值(Populate):set方法(bean标签的property子标签)、@Autowired等注入功能的注解
初始化(Initialization)
销毁(Destruction)
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// 1. 实例化
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object exposedObject = bean;
try {
// 2. 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// 3. 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// 4. 销毁-注册回调接口
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
return exposedObject;
}
// AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 3. 检查 Aware 相关接口并设置相关依赖
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 4. BeanPostProcessor 前置处理
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 5. 若实现 InitializingBean 接口,则调用 afterPropertiesSet() 方法,在属性注入完成后调用
// 6. 若配置自定义的 init-method方法,则执行
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 7. BeanPostProceesor 后置处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
// DisposableBeanAdapter.java
public void destroy() {
// 9. 若实现 DisposableBean 接口,则执行 destory()方法
if (this.invokeDisposableBean) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
((DisposableBean) this.bean).destroy();
}
}
}
// 10. 若配置自定义的 detory-method 方法,则执行
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
这些接口的实现类是独立于 Bean 的,并且会注册到 Spring 容器中。在 Spring 容器创建任何 Bean 的时候,这些后处理器都会发生作用。
该类是 BeanPostProcessor 的子接口,常用的有如下三个方法:
postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用
postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、构造方法前调用
postProcessAfterInstantiation(Class beanClass, String beanName):在实例化 Bean 之后、构造方法之后调用
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return pvs;
}
}
组件的“觉醒”
Aware 之前的名字就是可以拿到什么资源,例如 BeanNameAware 可以拿到 BeanName,以此类推。
调用时机:所有的 Aware 方法都是在初始化阶段之前调用的
若 Spring 检测到 bean 实现了 Aware 接口,则会为其注入相应的依赖。
–> 通过让 bean 实现 Aware 接口,则能在 bean 中获得相应的 Spring 容器资源。
当组件实现Aware接口的时候,会实现Aware接口里提供的 setXXX方法
这些 setXXX方法可以让组件对象获取一些信息,形参中会包含对应的信息,比如组件在容器中的组件id等
Spring 中提供的 Aware 接口:
BeanNameAware:该接口只有一个方法 setBeanName(String name),用来获取 bean 的 id 或者 name。
BeanClassLoaderAware:该接口只有一个方法 setBeanClassLoader(ClassLoader bc1),用来获取 bean 的 ClassLoader。
BeanFactoryAware:该接口只有一个方法 setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory。
// AbstractAutowireCapableBeanFactory.java
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
Spring 中提供的 Aware 接口:常用:
ApplicationContextAware:该接口只有一个方法 setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext。
// ApplicationContextAwareProcessor.java
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) { // 注入 Enviroment,一般用于获取配置属性
((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) { // 注入 EmbeddedValueResolver(Spring EL解析器),一般用于参数解析
((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware)bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
BeanPostProcessor 是 Spring 为修改 bean 提供的强大扩展点,其可作用于容器中除它本身外所有 bean
常用于:为当前对象提供代理实现。例如 Spring AOP 功能,生成对象的代理类,然后返回
该接口有两个方法:
postProcessBeforeInitialization(Object bean, String beanName):初始化前置处理,在初始化之前调用此方法
postProcessAfterInitialization(Object bean, String beanName):初始化后置处理,在初始化之后调用此方法
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
// AbstractAutoProxyCreator.java
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理类
return proxy;
}
return null;
}
从Java EE 5规范开始,Servlet 中增加了两个影响 Servlet 生命周期的注解:@PostConstruct和@PreDestroy。
被 @PostConstruct 修饰的方法会在服务器加载 Servlet 的时候运行,并且只会被服务器调用一次,类似于 Servlet 的 init() 方法。
被 @PostConstruct 修饰的方法会在构造函数之后,init() 方法之前运行。
被 @PreDestroy 修饰的方法会在服务器卸载 Servlet 的时候运行,并且只会被服务器调用一次,类似于 Servlet 的 destroy() 方法。
被 @PreDestroy 修饰的方法会在 destroy() 方法之后运行,在 Servlet 被彻底卸载之前。
dao层:
@Getter
@ToString
@Repository
public class UserDao implements InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware {
private Integer id;
private String name;
// 1-1. 实例化 Bean 实例:调用构造方法
public UserDao(Integer id, String name) {
this.id = id;
this.name = name;
System.out.println("调用全参构造函数");
}
// 1-1. 实例化 Bean 实例:调用构造方法
// 具体使用哪一个构造方式看 new 对象
public UserDao() {
System.out.println("调用无参构造函数");
}
// 2. 设置对象属性 属性注入
public void setId(Integer id) {
this.id = id;
System.out.println("\n2. 设置对象属性");
System.out.println("id属性注入");
}
// 2. 设置对象属性 属性注入
public void setName(String name) {
this.name = name;
System.out.println("name属性注入");
}
// 3. 初始化--检查 Aware 相关接口并设置相关依赖
// BeanNameAware 下的 setBeanName 方法
@Override
public void setBeanName(String name) {
System.out.println("\n3. 初始化");
System.out.println("调用 BeanNameAware.setBeanName() 方法");
}
// 3。 初始化--检查 Aware 相关接口并设置相关依赖
// ApplicationContextAware 下的 setApplicationContext 方法
// if (bean instanceof ApplicationContextAware) {
// ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
// }
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
System.out.println("3. 检查 Aware 相关接口并设置相关依赖---调用 ApplicationContextAware.setApplicationContext() 方法");
}
// 4. BeanPostProcessor 前置处理 见 MyBeanPostProcessor类
// 5. 初始化--是否实现 InitializingBean 接口
// InitializingBean 下的 afterPropertiesSet 方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("5. 是否实现 InitializingBean 接口---调用 InitializingBean.afterPropertiesSet() 方法");
}
// 6. 初始化--是否配置自定义的 init-method
@PostConstruct
public void myInit() {
System.out.println("6. 是否配置自定义的 init-method---调用 init-method 方法");
}
// 7. BeanPostProcessor 后置处理 见 MyBeanPostProcessor类
// 8. 注册 Destruction 相关回调接口 略
// 9. 销毁--是否实现 DisposableBean 接口
// DisposableBean 下的 destroy 方法
@Override
public void destroy() throws Exception {
System.out.println("\n4. 销毁");
System.out.println("调用 DisposableBean.destroy() 方法");
}
// 10. 销毁--是否配置自定义的 destroy-method
@PreDestroy
public void myDestroy() throws Exception {
System.out.println("调用 destroy-method 方法");
}
}
@Repository
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
// 1-0. 实例化 Bean 实例
// InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法 在实例化 Bean 之前调用
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userDao".equals(beanName)) {
System.out.println("1. 实例化 Bean 实例");
System.out.println("调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法");
}
return null;
}
// 1-1. 实例化 Bean 实例:调用全参构造方法 见 UserDao
// 1-2. 实例化 Bean 实例
// InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法 在实例化 Bean 之后、构造方法之前调用
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userDao".equals(beanName)) {
UserDao userDao = (UserDao) bean;
System.out.println("调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法");
}
return true;
}
// 1-3. 实例化 Bean 实例
// InstantiationAwareBeanPostProcessor.postProcessProperties() 方法 在实例化 Bean 之后、构造方法之后调用
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("userDao".equals(beanName)) {
System.out.println("调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法");
}
return null;
}
}
@Repository
public class MyBeanPostProcessor implements BeanPostProcessor {
// 4. 初始化--BeanPostProcessor 前置处理
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userDao".equals(beanName)) {
System.out.println("4. BeanPostProcessor 前置处理---调用 BeanPostProcessor.postProcessBeforeInitialization() 方法");
}
return bean;
}
// 7.初始化--BeanPostProcessor 后置处理
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userDao".equals(beanName)) {
System.out.println("7. BeanPostProcessor 后置处理---调用 BeanPostProcessor.postProcessAfterInitialization() 方法");
}
return bean;
}
}
@Configuration
public class MyConfig {
// @Bean(initMethod = "myInit", destroyMethod = "destroy") // 不执行 myDestroy
@Bean(initMethod = "myInit", destroyMethod = "myDestroy") // 执行 myDestroy 和 destroy
public UserDao userDao() {
return new UserDao(23, "xiaoyu-alive");
}
@Bean
public MyInstantiationAwareBeanPostProcessor myInstantiationAwareBeanPostProcessor() {
return new MyInstantiationAwareBeanPostProcessor();
}
@Bean
public MyBeanPostProcessor myBeanPostProcessor() {
return new MyBeanPostProcessor();
}
}
测试类:
@SpringBootTest
public class SpringbootdemoApplicationTests {
@Test
public void test() throws Exception {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
Object userDao = applicationContext.getBean("userDao");
// 销毁方法只有在IOC容器关闭的时候才调用,所以在测试代码中关闭IOC容器
//关闭ioc容器
applicationContext.close();
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean class="com.test.springbootdemo.dao.MyInstantiationAwareBeanPostProcessor">bean>
<bean id="userDao" class="com.test.springbootdemo.dao.UserDao">
<property name="id" value="23"/>
<property name="name" value="xiaoyu-alive">property>
bean>
<bean class="com.test.springbootdemo.dao.MyBeanPostProcessor">bean>
beans>
@Test
public void mytest() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml"); // 也可以使用绝对路径
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
((AbstractApplicationContext) applicationContext).close();
}
注:取消 MyInstantiationAwareBeanPostProcessor 和 MyBeanPostProcessor 的注入的测试结果:
参考:
如何记忆 Spring Bean 的生命周期
Spring注解(六):Bean的生命周期中自定义初始化和销毁方法的四种方式 右键 在新标签页中打开链接
一文读懂 Spring Bean 的生命周期