目录
1. 关于bean的生命周期
bean的生命周期是指bean从创建到初始化到销毁的过程,bean的生命周期由IoC容器进行管理。Spring允许我们自定义bean的生命周期方法,并在bean的生命周期过程中进行回调。
2. bean的生命周期方法全解
2.1 通过@Bean指定initMethod和destroyMethod
创建一个Car类,并自定义初始化方法initMethod()和销毁方法destroyMethod()。
public class Car{
public Car() {
System.out.println("Car constructor.......");
}
//自定义初始化方法
public void initMethod(){
System.out.println("Car init........");
}
//自定义销毁方法
public void destroyMethod(){
System.out.println("Car destroy......");
}
}
如何让Spring知道initMethod()是自定义的初始化方法,destroyMethod()是自定义的销毁方法?通过指定@Bean注解的initMethod属性和destroyMethod属性,值填方法名。
@Configuration
public class MainConfigOfLifeCycle {
@Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
public Car car() {
return new Car();
}
}
测试代码如下
@Test
public void test1(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器启动完成.........");
context.destroy();
}
运行得到测试结果如下
注意以上的例子是针对单实例bean而言(默认即为单实例),对于scope为prototype的bean,在第一次获取时才创建,且容器不会执行自定义的销毁方法。
2.2 实现InitializingBean或DisposableBean接口
InitializingBean也可以对bean进行自定义初始化,当bean的所有属性都已经注入完成后,该接口的方法会被Spring容器回调。
public interface InitializingBean {
/**
* Invoked by a BeanFactory after it has set all bean properties supplied
* (and satisfied BeanFactoryAware and ApplicationContextAware).
* <p>This method allows the bean instance to perform initialization only
* possible when all bean properties have been set and to throw an
* exception in the event of misconfiguration.
* @throws Exception in the event of misconfiguration (such
* as failure to set an essential property) or if initialization fails.
*/
void afterPropertiesSet() throws Exception;
同理,DisposableBean接口允许用户自定义销毁逻辑
public interface DisposableBean {
/**
* Invoked by a BeanFactory on destruction of a singleton.
* @throws Exception in case of shutdown errors.
* Exceptions will get logged but not rethrown to allow
* other beans to release their resources too.
*/
void destroy() throws Exception;
}
创建一个Cat类,实现上述两个接口并重写相关抽象方法
public class Cat implements InitializingBean,DisposableBean {
/**
* 实现DisposableBean接口重写
* @throws Exception
*/
public void destroy() throws Exception {
System.out.println("Cat DisposableBean destroy......");
}
/**
* 实现InitializingBean接口重写
* @throws Exception
*/
public void afterPropertiesSet() throws Exception {
System.out.println("Cat InitializingBean afterPropertiesSet.....");
}
}
配置类和测试代码如下
@Configuration
public class MainConfigOfLifeCycle {
// @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
// public Car car() {
// return new Car();
// }
@Bean
public Cat cat(){
return new Cat();
}
}
@Test
public void test1(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器启动完成.........");
context.destroy();
}
最后得到测试结果如下
2.3 使用@PostConstruct和@PreDestroy注解
这是JSR250中定义的两个注解。
@PostConstruct注解只能被使用在方法上,当bean的依赖已经注入完成并进行初始化前,被该注解标注的方法将被Spring容器回调。
* The PostConstruct annotation is used on a method that needs to be executed
* after dependency injection is done to perform any initialization
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}
同样,@PreDestroy注解也只能被用在方法上,在bean被从容器中移除前,被该注解标注的方法将被Spring容器回调。
* The PreDestroy annotation is used on methods as a callback notification to
* signal that the instance is in the process of being removed by the
* container
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}
自定义Dog类并在自定义方法上标注上这俩注解
public class Dog {
@PostConstruct
public void postConstruct(){
System.out.println("Dog PostConstruct.....");
}
@PreDestroy
public void preDestroy(){
System.out.println("Dog PreDestroy....");
}
}
最后测试结果如下
2.4 使用Bean的后置处理器接口BeanPostProcessor
这是容器级别的对bean的生命周期进行自定义的方式。ApplicationContext会自动注册实现了BeanPostProcessor接口的类,并将我们自定义的生命周期方法作用域每一个Bean的生命周期过程中。
BeanPostProcessor接口的定义如下,
该接口主要有两个抽象方法
public interface BeanPostProcessor {
/**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding {@code bean instanceof FactoryBean} checks.
* <p>This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other BeanPostProcessor callbacks.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
postProcessBeforeInitialization
在bean初始化前(InitializingBean接口的afterPropertiesSet方法被调用前以及自定义的init-method方法被调用前)做些自定义的工作postProcessAfterInitialization
在bean完成初始化后(InitializingBean接口的afterPropertiesSet方法被调用后以及自定义的init-method方法被调用后)做些自定义工作- 创建Bean
public class Cat{
public Cat() {
System.out.println("Cat constructor.......");
}
}
public class Dog {
public Dog() {
System.out.println("Dog constructor.......");
}
}
- 配置类
@Configuration
public class MainConfigOfLifeCycle {
@Bean
public BeanPostProcessor postProcessor() {
return new MyBeanPostProcessor();
}
@Bean
public Dog dog() {
return new Dog();
}
@Bean
public Cat cat() {
return new Cat();
}
}
- 测试代码
@Test
public void test1(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器启动完成.........");
context.destroy();
}
- 测试结果
可以看到,BeanPostProcessor提供了容器级别的,对所有bean都生效的生命周期增强手段。
3. 生命周期方法的执行顺序
- Bean的类定义
public class Car implements InitializingBean,DisposableBean{
public Car() {
System.out.println("Car constructor.......");
}
//自定义初始化方法
public void initMethod(){
System.out.println("Car init........");
}
//自定义销毁方法
public void destroyMethod(){
System.out.println("Car destroy......");
}
//实现DisposableBean接口
public void destroy() throws Exception {
System.out.println("Car DisposableBean destroy......... ");
}
//实现InitializingBean接口
public void afterPropertiesSet() throws Exception {
System.out.println("Car InitializingBean afterPropertiesSet..... ");
}
@PostConstruct
public void postConstructor(){
System.out.println("Car postConstructor.......");
}
@PreDestroy
public void preDestroy(){
System.out.println("Car preDestroy....");
}
}
- 自定义BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName+"=》"+"postProcessBeforeInitialization......");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName+"=》"+"postProcessAfterInitialization");
return bean;
}
}
- 测试代码
@Test
public void test1(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
System.out.println("容器启动完成.........");
context.destroy();
}
- 运行结果