【小家Spring】Spring注解驱动开发---Spring Ioc容器中Bean的生命周期详解(BeanPostProcessor解析)
每篇一句
只顾眼前的利益,得到的只是短暂的欢愉;目标高远,但也要面对现实。把理想和现实结合起来,才有可能成功
前言
bean的生命周期指的是bean创建—初始化到销毁的过程。
我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
单实例:在容器启动的时候创建对象
多实例:容器不会管理这个bean;容器不会调用销毁方法;
Bean生命周期初始化、销毁相关的4种方式
1、@Bean指定初始化方法和销毁方法 initMethod destroyMethod
initMethod 指定Bean创建后调用的初始化方法
destroyMethod 指定Bean在销毁后会调用的方法
栗子:略
2、实现InitializingBean和DisposableBean接口
将要创建指定初始化和销毁方法的类实现初始化接口InitializingBean,如果需要指定销毁方法实现DisposableBean接口
public class InitAndDisposableBean implements InitializingBean, DisposableBean {
public InitAndDisposableBean() {
System.out.println("InitAndDisposableBean创建完成。。。。。。。。。。。。");
}
@Override
public void destroy() throws Exception {
System.out.println("InitAndDisposableBean容器销毁,实现DisposableBean接口调用销毁方法...........");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitAndDisposableBean创建后实现InitializingBean调用初始化方法。。。。。。。。。。。。");
}
}
3、使用JSR250规范:@PostContruct、@PreDestroy
在需要指定初始化和销毁方法的Bean里创建对应的初始化和销毁方法,使用对应注解标注即可。
使用@PostConstruct指定Bean的初始化方法
使用@PreDestroy指定Bean销毁方法
@Component
public class Student {
@PostConstruct
public void init(){
System.out.println("Student postConstruct...");
}
@PreDestroy
public void destroy(){
System.out.println("Student preDestroy...");
}
}
很多人迷糊@PostConstruct
会在构造函数之前执行还是之后执行呢?其实从单词中也能见名知意(此处以servlet为例):被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行
被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前
栗子:略
4、BeanPostProcessor接口
public interface BeanPostProcessor {
//在任何初始化方法(例如上面的三种方式,定义的init方法,@PostConstruct,接口InitializingBean的方法)调用之前工作
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//这个是在上面的初始化方法调用之后工作
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
Bean的后置处理器,在bean初始化前后处理一些工作,就是在上面三种初始化(init,@PostConstruct,InitializingBean接口)调用的前后做一些工作的处理.。通过这个方法可以对bean进行一些包装和处理。
BeanPostProcessor
在Spring中有大量的应用。它提供了功能相当于我们可以在Bean放进Ioc容器前后做些事情,比如包装、生成代理对象等一般都是通过此接口实现的。当把Bean放进去时,Spring会调用配置执行的所有的BeanPostProcessor
。
比如解析@Async
、@Autowired
的AutowiredAnnotationBeanPostProcessor
后置处理器
postProcessBeforeInitialization()在每个bean创建之后的初始化方法之前调用,
postProcessAfterInitialization在每个bean的初始化方法执行之后被调用,该方法通常用户修改预定义的bean的属性值,可以实现该接口进行覆盖。(该方法特别的重要,可以做一些全局统一处理的操作)
关于BeanPostProcessor
的使用,后续必须还有专门的文章进行分析,此处制作简单的一个生命周期相关的讨论。
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
/**
* 在每个bean创建之后的初始化方法之前调用
* @param bean 当前实例化的bean
* @param beanName bean的名称
* @return 返回实例化的bean或者可以对对象进行再封装返回
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor的postProcessBeforeInitialization方法执行,当前bean【" + bean + "】");
return bean;
}
/**
* 在每个bean的初始化方法执行之后被调用
* @param bean 当前实例化的bean
* @param beanName bean的名称
* @return 返回实例化的bean或者可以对对象进行再封装返回
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor的postProcessAfterInitialization方法执行,当前bean【" + bean + "】");
return bean;
}
}
需要注意的是:实现这个接口的类,需要放入IOC容器中才会生效
总结
Spring提供了多种方式,让我们可以参与控制Bean的生命周期,从而达到我们的业务目的。相信有了这些功能之后,我们处理起来就会更加的游刃有余了。
备注:
1、实现InitializingBean接口是直接调用afterPropertiesSet方法,而init-method是通过反射来实现,效率较低,但是init-method方式消除了对spring的依赖。
2、InitializingBean接口实现先于init-method方法,如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法(画外音:若不出错,就都会调用)。
知识交流
若群二维码失效,请加微信号(或者扫描下方二维码):fsx641385712。
并且备注:“java入群” 字样,会手动邀请入群