前言
Bean的生命周期指的是Bean从被创建到初始化再被销毁的过程,IOC容器管理Bean的生命周期。在Bean的整个生命周期的过程中的初始化和销毁过程的方法可以被自定义,IOC容器当Bean进行到当前生命周期的时候调用自定义的初始化和销毁方法。在配置文件中可以通过添加init-method和destroy-method指定自定义的初始化和销毁方法,如下:
<bean id="Person" class="com.xinyi.bean.Person" init-method="" destroy-method=""> 复制代码
在Spring注解开发中有四种自定义初始化和销毁方法。
1、使用@Bean注解指定初始化和销毁方法
新建一个Fruit类,并自定义初始化和销毁方法,如下:
public class Fruit { public Fruit() { System.out.println("Fruit被创建"); } public void init() { System.out.println("Fruit被初始化"); } public void destroy() { System.out.println("Fruit被销毁"); } } 复制代码
配置类中使用@Bean注解注册组件,并测试
@Configuration public class MyConfig2 { @Bean public Fruit fruit() { return new Fruit(); } } 复制代码
//测试声明周期 @Test public void test5() { //创建ioc容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig2.class); System.out.println("IOC容器创建完成"); } 复制代码
在@Bean注解的参数中指定Fruit类自定义的初始化和销毁方法:
@Bean(initMethod = "init",destroyMethod = "destroy") 复制代码
销毁方法只有在IOC容器关闭的时候才调用,所以在测试代码中关闭IOC容器:
//关闭ioc容器 applicationContext.close(); 复制代码
所以可以通过@Bean注解参数的initMethod和destroyMethod指定自定义的初始化和销毁的方法。并且初始化方法在对象创建完成后调用,在文章Spring注解(三):@scope设置组件作用域中提到当组件的作用域为单例时在容器启动时即创建对象,而当作用域为原型(PROTOTYPE)时在每次获取对象的时候才创建对象。并且当作用域为原型(PROTOTYPE)时,IOC容器只负责创建Bean但不会管理Bean,所以IOC容器不会调用销毁方法。
2、Bean实现InitializingBean接口和DisposableBean接口自定义初始化和销毁逻辑
首先我们看看关于InitializingBean接口的源码:
public interface InitializingBean { /** * Bean都装配完成后执行初始化 */ void afterPropertiesSet() throws Exception; 复制代码
接着再来看看DisposableBean接口源码:
public interface DisposableBean { /** * Invoked by the containing {@code BeanFactory} on destruction of a bean. * @throws Exception in case of shutdown errors. Exceptions will get logged * but not rethrown to allow other beans to release their resources as well. */ void destroy() throws Exception; } 复制代码
public class Fruit01 implements InitializingBean,DisposableBean { public void afterPropertiesSet() throws Exception { System.out.println("Fruit01初始化"); } public void destroy() throws Exception { System.out.println("Fruit01销毁"); } public Fruit01() { System.out.println("Fruit01被创建"); } } 复制代码
上述就是通过实现InitializingBean接口和DisposableBean接口自定义初始化和销毁逻辑的方法。
3、使用@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解
从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解,分别是:@PostConstruct和@PreDestroy。
被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。
被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。
被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。
这里再创建一个Fruit02类,如下:
public class Fruit02 { public Fruit02() { System.out.println("Fruit02创建"); } //对象创建并赋值之后调用 @PostConstruct public void init() { System.out.println("Fruit02初始化"); } //对象被从ioc容器中移除之前调用 @PreDestroy public void destroy() { System.out.println("Fruit02被销毁"); } } 复制代码
4、使用BeanPostProcessor接口
BeanPostProcessor又叫Bean的后置处理器,是Spring框架中IOC容器提供的一个扩展接口,在Bean初始化的前后进行一些处理工作。BeanPostProcessor的源码如下:
public interface BeanPostProcessor { @Nullable //bean初始化方法调用前被调用 default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Nullable //bean初始化方法调用后被调用 default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } 复制代码
public class MyBeanPostProcessor implements BeanPostProcessor{ //bean初始化方法调用前被调用 public Object postProcessBeforeInitialization(Object bean, String beanName) { System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean); return bean; } //bean初始化方法调用后被调用 public Object postProcessAfterInitialization(Object bean, String beanName) { System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean); return bean; } } 复制代码
通过上述运行结果可以发现使用BeanPostProcessor的运行顺序为:
IOC容器实例化Bean---->调用BeanPostProcessor的postProcessBeforeInitialization方法---->调用bean实例的初始化方法---->调用BeanPostProcessor的postProcessAfterInitialization方法
结尾
Bean 的生命周期指的是Bean的被创建、初始化、销毁的过程,以上就是Bean的生命周期过程中通过自定义初始化和销毁方法的四种方式。