Bean的生命周期指的是Bean从被创建到初始化再被销毁的过程,IOC容器管理Bean的生命周期。在Bean的整个生命周期的过程中的初始化和销毁过程的方法可以被自定义,IOC容器当Bean进行到当前生命周期的时候调用自定义的初始化和销毁方法。在配置文件中可以通过添加init-method和destroy-method指定自定义的初始化和销毁方法,如下:
<bean id="Person" class="com.xinyi.bean.Person" init-method="" destroy-method="">
在Spring注解开发中有四种自定义初始化和销毁方法。
新建一个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容器不会调用销毁方法。
InitializingBean接口源码:
public interface InitializingBean {
/**
* Invoked by the containing {@code BeanFactory} after it has set all bean properties
* and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
* This method allows the bean instance to perform validation of its overall
* configuration and final initialization when all bean properties have been set.
* @throws Exception in the event of misconfiguration (such as failure to set an
* essential property) or if initialization fails for any other reason
* 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接口自定义初始化和销毁逻辑的方法。
从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解:@PostConstruct和@PreDestroy。
被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。
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被销毁");
}
}
BeanPostProcessor又叫Bean的后置处理器,是Spring框架中IOC容器提供的一个扩展接口,在Bean初始化的前后进行一些处理工作。BeanPostProcessor的源码如下:
public interface BeanPostProcessor {
/**
* Apply this BeanPostProcessor to the given new bean instance before 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.
* The default implementation returns the given {@code bean} as-is.
* @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
*/
@Nullable
//bean初始化方法调用前被调用
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* Apply this BeanPostProcessor to the given new bean instance after 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.
* 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.
*
This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other BeanPostProcessor callbacks.
*
The default implementation returns the given {@code bean} as-is.
* @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
*/
@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方法