文章目录
1 Bean的生命周期
bean的声明周期:
- 创建
- 初始化
- 销毁
我们可以自定义初始化和销毁方法,容器在bean执行到当前生命周期的时候来调用自己定义的初始化和销毁逻辑
为了演示bean声明周期,将在创建一个新的包,用于测试演示。
1.1 创建
之前已经提过:
单实例:在容器启动的时候创建
多实例:在每次获取的时候创建
1.2 初始化
单实例:对象创建完,并赋值好,调用初始化方法
多实例:对象创建完,并赋值好,调用初始化方法
1.3 销毁
单实例:容器关闭的时候执行销毁逻辑
多实例:容器不会管理这个Bean,容器不会调用销毁方法,需要自己手动调用
2 @Bean注解中指定初始化和销毁方法
2.1 使用
- 定义一个Bean:LifeBean
@Slf4j
public class LifeBean {
public LifeBean() {
log.info("LifeBean constructor。。。");
}
public void init(){
log.info("LifeBean init。。。");
}
public void destroy(){
log.info("LifeBean destroy。。。");
}
}
- 定义一个配置类,指定包扫描和配置刚刚的bean
@Configuration
// 只扫描这包,为了不让之前的会测试代码污染我们的测试效果
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {
@Bean(initMethod = "init",destroyMethod = "destroy")
public LifeBean lifeBean(){
return new LifeBean();
}
}
- initMethod: 指定bean初始化逻辑的方法
- destroyMethod: 指定bean逻辑的销毁方法
- 测试
/**
* 测试单实例bean的声明周期
*/
@Test
public void test01(){
// 创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
log.info("ioc容器创建完成。。。");
}
日志结果:
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean init。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。
可见在单实例在容器创建完成时,就完成单实例bean的创建和初始化
那何时销毁呢—>在容器关闭的时候:
@Test
public void test01(){
// 创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
log.info("ioc容器创建完成。。。");
applicationContext.close();
}
日志结果:
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean init。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean destroy。。。
上面测试的是单实例bean的生命周期
下面测试多实例bean的声明周期,使用@Scope注解
@Configuration
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {
@Bean(initMethod = "init",destroyMethod = "destroy")
@Scope("prototype")
public LifeBean lifeBean(){
return new LifeBean();
}
}
/**
* 测试多实例bean的声明周期
*/
@Test
public void test02(){
// 创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
log.info("ioc容器创建完成。。。");
LifeBean bean = applicationContext.getBean(LifeBean.class);
applicationContext.close();
}
日志结果:
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean - LifeBean init。。。
发现多实例在每次获取的时候执行创建和初始化,但是容器关闭的时候不会执行销毁逻辑
3 InitializingBean , DisposableBean
3.1 介绍
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.
*/
// bean的属性设置完成之后执行
void afterPropertiesSet() throws Exception;
}
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;
}
3.2 演示
- 定义一个Bean实现这两个接口
@Slf4j
public class LifeBean2 implements InitializingBean , DisposableBean {
public LifeBean2() {
log.info("LifeBean2 constructor。。。");
}
/**
* 销毁的时候执行
* @throws Exception
*/
@Override
public void destroy() throws Exception {
log.info("LifeBean2 destroy。。。");
}
/**
* bean的属性设置完成之后执行
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
log.info("LifeBean2 afterPropertiesSet。。。");
}
}
- 配置这个bean
为了不影响避免过多日志输出,先不注册之前演示的Bean
@Configuration
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {
/*@Bean(initMethod = "init",destroyMethod = "destroy")
@Scope("prototype")
public LifeBean lifeBean(){
return new LifeBean();
}*/
@Bean
public LifeBean2 lifeBean2(){
return new LifeBean2();
}
}
- 测试
/**
* 测试单实例bean的声明周期
*/
@Test
public void test01(){
// 创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
log.info("ioc容器创建完成。。。");
applicationContext.close();
}
日志结果:
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 afterPropertiesSet。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 destroy。。。
/**
* 测试多实例bean的声明周期
*/
@Test
public void test03(){
// 创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
log.info("ioc容器创建完成。。。");
LifeBean2 bean = applicationContext.getBean(LifeBean2.class);
applicationContext.close();
}
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean2 - LifeBean2 afterPropertiesSet。。。
4 JSR250
@PostConstruct
: bean创建完成并属性赋值完成的时候执行@PreDestroy
: 容器销毁的对象的前通知
@Slf4j
public class LifeBean3 {
public LifeBean3() {
log.info("LifeBean3 constructor。。。");
}
/**
* 容器销毁的对象的前通知
* @throws Exception
*/
@PreDestroy
public void destroy() throws Exception {
log.info("LifeBean2 destroy。。。");
}
/**
* bean创建完成并属性赋值完成的时候执行
* @throws Exception
*/
@PostConstruct
public void afterPropertiesSet() throws Exception {
log.info("LifeBean2 afterPropertiesSet。。。");
}
}
@Configuration
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {
@Bean
public LifeBean3 lifeBean3(){
return new LifeBean3();
}
}
@Test
public void test04(){
// 创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
log.info("ioc容器创建完成。。。");
LifeBean3 bean = applicationContext.getBean(LifeBean3.class);
applicationContext.close();
}
[main] INFO study.wyy.spring.anno.life.bean.LifeBean3 - LifeBean3 constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean3 - LifeBean2 afterPropertiesSet。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean3 - LifeBean2 destroy。。。
5 三者比较
上述提供的3个初始化和销毁的方式,这三个之间的顺序又是如何呢
- 一个Bean通过上面三个方式进行初始化
@Slf4j
public class LifeBean4 implements InitializingBean , DisposableBean {
public LifeBean4() {
log.info("LifeBean4 constructor。。。");
}
/**
* 销毁的时候执行
* @throws Exception
*/
@Override
public void destroy() throws Exception {
log.info("LifeBean4 destroy。。。");
}
/**
* bean的属性设置完成之后执行
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
log.info("LifeBean4 afterPropertiesSet。。。");
}
@PostConstruct
public void postConstruct(){
log.info("LifeBean4 postConstruct。。。");
}
@PreDestroy
public void preDestroy(){
log.info("LifeBean4 preDestroy。。。");
}
public void init(){
log.info("LifeBean4 init。。。");
}
public void destroyOnBean(){
log.info("LifeBean4 destroyOnBean。。。");
}
}
- 配置
@Configuration
@ComponentScan("study.wyy.spring.anno.life")
public class MainLiftCycleConfig {
@Bean(initMethod = "init",destroyMethod = "destroyOnBean")
public LifeBean4 lifeBean4(){
return new LifeBean4();
}
}
- 测试
@Test
public void test05(){
// 创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
log.info("ioc容器创建完成。。。");
LifeBean4 bean = applicationContext.getBean(LifeBean4.class);
applicationContext.close();
}
- 日志输出
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 constructor。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 postConstruct。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 afterPropertiesSet。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 init。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 preDestroy。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 destroy。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 destroyOnBean。。。
可见初始化和销毁的时候这三个顺序:
@postConstruct
InitializingBean
@Bean
6 BeanPostProcessor
6.1 BeanPostProcessor介绍
可以对Spring容器扫描到的Bean在初始化前后进行增强处理
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
*/
/**
*
* @param bean : 当前的处理Bean
* @param beanName 当前Bean的name
* @return 可以返回当前的Bean也可以返回当前Bean的包装
* @throws BeansException
* 初始化(afterPropertiesSet,init-method)之前
*/
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
*/
/**
*
* @param bean 当前的处理Bean
* @param beanName 当前Bean的name
* @return 可以返回当前的Bean也可以返回当前Bean的包装
* @throws BeansException
* 初始化(afterPropertiesSet,init-method)之后
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
6.2 BeanPostProcessor测试
/*
* @author :wyaoyao
* @date : 2020-06-14 22:09
* BeanPostProcessor:Bean初始化前后进行增强处理
*/
@Slf4j
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
*
* @param bean : 当前的处理Bean
* @param beanName 当前Bean的name
* @return 可以返回当前的Bean也可以返回当前Bean的包装
* @throws BeansException
* 初始化之前
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof LifeBean4){
log.info("lifeBean4 postProcessBeforeInitialization。。。");
}
return bean;
}
/**
*
* @param bean 当前的处理Bean
* @param beanName 当前Bean的name
* @return 可以返回当前的Bean也可以返回当前Bean的包装
* @throws BeansException
* 初始化之后
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof LifeBean4){
log.info("lifeBean4 postProcessAfterInitialization。。。");
}
return bean;
}
}
- 测试
@Test
public void test05(){
// 创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainLiftCycleConfig.class);
log.info("ioc容器创建完成。。。");
LifeBean4 bean = applicationContext.getBean(LifeBean4.class);
applicationContext.close();
}
- 日志
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 constructor。。。
[main] INFO study.wyy.spring.anno.life.config.MyBeanPostProcessor - lifeBean4 postProcessBeforeInitialization。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 postConstruct。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 afterPropertiesSet。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 init。。。
[main] INFO study.wyy.spring.anno.life.config.MyBeanPostProcessor - lifeBean4 postProcessAfterInitialization。。。
[main] INFO lifetest.Test01 - ioc容器创建完成。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 preDestroy。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 destroy。。。
[main] INFO study.wyy.spring.anno.life.bean.LifeBean4 - LifeBean4 destroyOnBean。。。