本文最后更新于:2022年5月12日 凌晨
摘要:介绍了bean的生命周期以及执行时机、如何指定bean各个生命周期执行的方法。
Bean的生命周期基础
bean生命周期是指bean从创建——>初始化——>销毁的过程。容器管理bean的生命周期:自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候,调用自定义的初始化和销毁方法。
构造(对象创建)
单实例:容器创建的时候创建对象
多实例:每次获取的时候创建对象
初始化:
销毁:
指定初始化和销毁方法
通过@Bean指定指定init-method 和 destroy-method
- 创建一个Phone类,并在里面定义初始化和销毁方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.shg.bean;
public class Phone { public Phone() { System.out.println("phone constructor ..."); }
public void init() { System.out.println("phone init ..."); }
public void destroy() { System.out.println("phone destroy ..."); } }
|
- 在配置类中,通过@Bean注解的参数initMethod和destroyMethod指定初始化和销毁方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.shg.config;
import com.shg.bean.Phone; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;
@Configuration public class MyConfig1 {
@Bean(initMethod = "init", destroyMethod = "destroy") public Phone phone() { return new Phone(); } }
|
- 创建一个测试类,查看结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.shg.test;
import com.shg.config.MyConfig1; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class LifeCycleTest {
@Test public void test01() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig1.class); context.close();
} }
|
输出结果如下:
1 2 3
| phone constructor ... phone init ... phone destroy ...
|
实现InitializingBean和DisposableBean接口
通过在让注册的Bean实现InitializingBean接口中的afterPropertiesSet方法和DisposableBean接口destroy方法
- 定义一个Computer类,分别实现InitializingBean和DisposableBean接口
- InitializingBean#afterPropertiesSet():定义初始化逻辑
- DisposableBean#destroy():定义销毁逻辑
- 后续在配置类中使用@ComponentScan扫描组件的方式将组件注册到容器中,所以给该类加上@Component注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.shg.bean;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component;
@Component public class Computer implements InitializingBean, DisposableBean {
public Computer() { System.out.println("Computer.Computer"); }
@Override public void destroy() throws Exception { System.out.println("Computer.destroy"); }
@Override public void afterPropertiesSet() throws Exception { System.out.println("Computer.afterPropertiesSet"); } }
|
- 在配置类中通过@CompnentScan注解将Computer类(使用了@Component注解)注册到容器中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.shg.config;
import com.shg.bean.Phone; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;
@Configuration @ComponentScan("com.shg.bean") public class MyConfig1 {
@Bean(initMethod = "init", destroyMethod = "destroy") public Phone phone() { return new Phone(); } }
|
- 查看结果
1 2 3 4 5
| @Test public void test01() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig1.class); context.close(); }
|
1 2 3 4 5 6
| Computer.Computer Computer.afterPropertiesSet phone constructor ... phone init ... phone destroy ... Computer.destroy
|
使用JSR250规范中的注解
分别在初始化方法上加@PostConstruct、在销毁方法上加@PreDestroy,当容器在bean执行到对应生命周期会调用对应方法
- 定义一个Pad类,并在其初始化和销毁方法上加上注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package com.shg.bean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy;
@Component public class Pad { public Pad() { System.out.println("Pad.Pad"); }
@PostConstruct public void init() { System.out.println("Pad.init"); }
@PreDestroy public void destroy() { System.out.println("Pad.destroy"); } }
|
配置类同上,无需改动
查看输出结果(代码无需改动)
1 2 3 4 5 6 7 8 9
| Computer.Computer Computer.afterPropertiesSet Pad.Pad Pad.init phone constructor ... phone init ... phone destroy ... Pad.destroy Computer.destroy
|
BeanPostProcessor:bean的后置处理器
容器中有BeanPostProcessor接口的实现类,容器所管理的bean在初始化前后进行一些处理工作,在初始化之前会调用接口中的postProcessBeforeInitialization方法,在初始化之后会调用接口中的postProcessAfterInitialization方法。
- 定义BeanPostProcessor接口的实现类,并在类上加上@Component注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.shg.processor;
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component;
@Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization"); return bean; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("MyBeanPostProcessor.postProcessAfterInitialization"); return bean; } }
|
- 修改配置类
将类上面的注解@ComponentScan(“com.shg.bean”)修改为:@ComponentScan({“com.shg.bean”, “com.shg.processor”})
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.shg.config;
import com.shg.bean.Phone; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;
@Configuration @ComponentScan({"com.shg.bean", "com.shg.processor"}) public class MyConfig1 {
@Bean(initMethod = "init", destroyMethod = "destroy") public Phone phone() { return new Phone(); } }
|
- 查看输出结果
每个bean在构造方法之后、初始化方法之前会调用postProcessBeforeInitialization
在初始化方法之后、销毁方法之前会调用:postProcessAfterInitialization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| MyBeanPostProcessor.postProcessBeforeInitialization MyBeanPostProcessor.postProcessAfterInitialization Computer.Computer MyBeanPostProcessor.postProcessBeforeInitialization Computer.afterPropertiesSet MyBeanPostProcessor.postProcessAfterInitialization Pad.Pad MyBeanPostProcessor.postProcessBeforeInitialization Pad.init MyBeanPostProcessor.postProcessAfterInitialization phone constructor ... MyBeanPostProcessor.postProcessBeforeInitialization phone init ... MyBeanPostProcessor.postProcessAfterInitialization phone destroy ... Pad.destroy Computer.destroy
|
总结
bean的生命周期共分为:bean创建、初始化、销毁三个阶段。定义bean的初始化和销毁方法主要有:通过@Bean注解的init-method 和 destroy-method来指定、实现InitializingBean和DisposableBean接口中的对应方法、使用JSR250规范中的@PostConstructh和@PreDestroy注解。此外,如果容器中有BeanPostProcessor接口的实现类,在初始化方法执行的前后还会执行该接口中的postProcessBeforeInitialization和postProcessAfterInitialization方法。