一、Bean 的生命周期
??对于普通的 Java 对象,new 的时候会去创建对象,而当它没有任何引用的时候则被垃圾回收机制回收。相较于前者,由Spring IoC 容器托管的对象,它们的生命周期完全由容器控制。Spring 中每个 Bean 的生命周期如下:
- 对于 ApplicationContext 容器,当容器启动结束后,实例化所有的 Bean。
- 设置对象属性,即依赖注入,动态将依赖关系注入到对象中。
- 紧接着,Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的 xxxAware实例注入给 Bean。
- 当经过上述几个步骤后,Bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过
BeanPostProcessor接口实现。
该接口提供了两个函数:
- postProcessBeforeInitialzation( Object bean, String beanName ) 当前正在初始化的 Bean 对象会被传递进来,我们就可以对这个 Bean 作任何处理。 这个函数会先于 InitialzationBean 执行,因此称为前置处理。 所有 Aware 接口的注入就是在这一步完成的。
- postProcessAfterInitialzation( Object bean, String beanName ) 当前正在初始化的 Bean 对象会被传递进来,我们就可以对这个 Bean 作任何处理。 这个函数会在 InitialzationBean 完成后执行,因此称为后置处理。
- 当 BeanPostProcessor 的前置处理完成后就会进入以下阶段。
- 这一阶段也可以在 Bean 正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前 Bean 对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。 若要使用它,我们需要让 Bean 实现该接口,并把要增加的逻辑写在该函数中。然后 Spring 会在前置处理完成后检测当前 Bean 是否实现了该接口,并执行 afterPropertiesSet 函数。
InitializingBean 接口只有一个函数:afterPropertiesSet()
- 当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了 init-method 属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。 init-method本质上仍然使用了InitializingBean接口。
- 通过给 destroy-method 指定函数,就可以在 Bean 销毁前执行指定的逻辑。
二、代码演示
项目结构如下:(红框中为代码演示使用到)
创建启动入口类:org.example.AppLifecycle
package org.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppLifecycle {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("lifecycle.xml");
((ClassPathXmlApplicationContext) context).close();
}
}
Spring配置文件:在src/main/resources 下,创建lifecycle.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
<context:component-scan base-package="org.example.config"/>
</beans>
准备要进行生命周期管理的Bean对象,创建org.example.model.LifeCycleTest
package org.example.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class LifeCycleTest implements InitializingBean, DisposableBean, ApplicationContextAware, BeanNameAware, BeanFactoryAware {
public void beanInit(){
System.out.println("init-method: 注解是使用@Bean(initMethod=\"方法名\")的方式,xml是使用<bean init-method=\"方法名\" />");
}
@PostConstruct
public void postConstruct(){
System.out.println("@PostConstruct");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean");
}
public void beanDestroy(){
System.out.println("destroy-method: 注解是使用@Bean(destroyMethod=\"方法名\")的方式,xml是使用<bean destroy-method=\"方法名\" />");
}
@PreDestroy
public void preDestroy(){
System.out.println("@PreDestroy");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContextAware");
}
@Override
public void setBeanName(String name) {
System.out.println("BeanNameAware");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware");
}
}
使用创建的配置类org.example.config.AppConfig :
package org.example.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig implements BeanPostProcessor {
@Bean(initMethod = "beanInit", destroyMethod = "beanDestroy")
public LifeCycleTest lifeCycleTest(){
return new LifeCycleTest();
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor Before");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor After");
return bean;
}
}
代码运行结果
三、主要步骤简述
- 实例化 Bean:通过反射调用构造方法实例化对象。
- 依赖注入:装配 Bean 的属性。
- 实现了 Aware接口的 Bean,执行接口方法:如顺序执行 BeanNameAware、BeanFactoryAware、ApplicationContextAware的接口方法。
- Bean 对象初始化前,循环调用实现了 BeanPostProcessor 接口的预初始化方法(postProcessBeforeInitialization)。
- Bean 对象初始化:顺序执行 @PostConstruct 注解方法、InitializingBean 接口方法、init-method 方法。
- Bean 对象初始化后,循环调用实现了 BeanPostProcessor 接口的后初始化方法(postProcessAfterInitialization)。
- 容器关闭时,执行 Bean 对象的销毁方法,顺序是:@PreDestroy 注解方法、DisposableBean 接口方法、destroy-method。
补充说明:第一步的实例化是指new对象,Spring的语义中说初始化Bean包含Bean生命周期中的初始化步骤。
|