1、Spring中bean的初始化与销毁方法
spring的bean的生命周期大致可以分为以下部分:
1、对象的创建:单实例的Bean在容器初始化时创建,多实例Bean在每次获取的时候
2、属性的填充 populateBean
3、Aware接口的调用
4、BeanPostProcessor接口的postProcessBeforeInitialization调用
5、生命周期初始化方法:对象创建完成,并填充完属性之后
6、BeanPostProcessor接口的postProcessAfterInitialization调用
7、使用bean
8、生命周期销毁方法:单实例Bean在容器关闭时执行销毁方法,多实例的Bean是不放入容器中的,因此容器无法管理
在XML文件中的bean标签中可以配置生命周期初始化方法与生命周期销毁方法
<bean id="person" class="com.caopeng.bean.Person" destroy-method="init" init-method="destory"></bean>
那么在注解版本中,也可以通过@Bean注解中的一些属性来配置
1.1、类的定义
public class Car {
public Car() {
System.out.println("constructor");
}
public void init(){
System.out.println("init 方法");
}
public void destory(){
System.out.println("destory 方法");
}
}
1.2、java配置文件中注入Bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfigOfLifeCycle {
//通过initMethod与destroyMethod方法来指定初始化与销毁方法
@Bean(initMethod = "init",destroyMethod = "destory")
public Car car(){
return new Car();
}
}
1.3、测试
public class DemoLifeCycle {
@Test
public void fun01(){
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(AppConfigOfLifeCycle.class);
Object car = applicationContext.getBean("car");
// 关闭容器
applicationContext.close();
}
}
1.4、运行结果
constructor
init 方法
destory 方法
如果把Car变成多实例Bean
@Bean(initMethod = "init",destroyMethod = "destory")
@Scope("prototype")
public Car car(){
return new Car();
}
这样在容器关闭时就不会调用destory方法
2、通过实现InitializingBean接口与DisposableBean接口
2.1、InitializingBean
package org.springframework.beans.factory;
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
2.2、DisposableBean
package org.springframework.beans.factory;
public interface DisposableBean {
void destroy() throws Exception;
}
2.3、示例
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class Cat implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
}
3、JSR250中的@PostConstruct与@PreDestroy注解
@Component
public class Dog {
@PostConstruct
public void init(){
System.out.println("dog:init");
}
@PreDestroy
public void destroy(){
System.out.println("dog:destroy");
}
}
4、BeanPostProcessor接口
在bean填充完属性之后,还有一个方式可以初始化bean与销毁bean,就是定义一个实现BeanPostProcessor类。
4.1、BeanPostProcessor接口说明
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;
/**
允许自定义修改新bean实例的工厂回调方法,例如,检查标记接口或用代理包装bean。
ApplicationContext可以在其bean定义中自动检测出哪些是BeanPostProcessor类型的bean,并将这些后处理器应用于随后创建的任何bean。普通BeanFactory允许对后置处理器进行注册,将后置处理器应用于通过BeanFactory创建的所有bean。
*/
public interface BeanPostProcessor {
/*
1、在新的Bean实例的任何的初始化回调方法(例如:InitializingBean接口的afterPropertiesSet方法 或者自定义的init-method)调用之前,调用postProcessBeforeInitialization方法。
2、返回的实例可以是原来的对象 ,也可以是被包裹后的对象
3、默认实现按原样返回给定bean。
@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;
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
1、在初始化方法调用之后调用postProcessAfterInitialization,在InitializingBean接口的afterPropertiesSet方法 或者自定义的init-method调用之后工作
2、返回的实例可以是原来的对象 ,也可以是被包裹后的对象
3、默认实现按原样返回给定bean。
@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;
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
4.2、实例
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(beanName+">>>BeanPostProcessor::postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName+">>>BeanPostProcessor::postProcessAfterInitialization");
return bean;
}
}
4.3、运行结果
appConfigOfLifeCycle>>>BeanPostProcessor::postProcessBeforeInitialization
appConfigOfLifeCycle>>>BeanPostProcessor::postProcessAfterInitialization
cat>>>BeanPostProcessor::postProcessBeforeInitialization
Cat>>InitializingBean::afterPropertiesSet
cat>>>BeanPostProcessor::postProcessAfterInitialization
dog>>>BeanPostProcessor::postProcessBeforeInitialization
dog:init
dog>>>BeanPostProcessor::postProcessAfterInitialization
Car::constructor
car>>>BeanPostProcessor::postProcessBeforeInitialization
Car::init 方法
car>>>BeanPostProcessor::postProcessAfterInitialization
Car::destory 方法
dog:destroy
Cat>>>DisposableBean::destroy
BeanPostProcessor接口中的方法在spring中用户定义的所有bean都会起作用,而之前的三种配置方式只是针对特定的bean起作用
5、初始化方法的调用顺序原理
AbstractAutowireCapableBeanFactory类的createBean ->doCreateBean->populateBean以及initializeBean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//调用Aware接口
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用接口的前置方法postProcessBeforeInitialization
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用生命周期的初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//调用接口的后置方法postProcessAfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}