bean生命周期
bean生命周期指的是bean组件从创建到销毁的过程;bean生命周期由容器进行管理,但我们可以自定义初始化和销毁方法; 容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
指定初始化和销毁方法方式
1、通过@Bean里的 init-method 和 destroy-method 指定 初始化方法 和 销毁方法
2、通过让Bean实现InitializingBean(定义初始化逻辑)、DisposableBean(定义销毁逻辑)
3、使用JSR250:
@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
4、实现BeanPostProcessor-后置处理器:可以拦截bean初始化,并可以在被拦截的Bean的初始化前后进行一些处理工作。
postProcessBeforeInitialization: 在初始化之前工作
postProcessAfterInitialization: 在初始化之后工作
@Bean指定 初始化 和 销毁方法
使用xml的方式:
<bean id="cat" class="com.lly.pojo.Cat" init-method="init" destroy-method="destroy">
@Bean注解eg:pojo
public class Cat {
public Cat() {
System.out.println("Cat constructor");
}
public void init() {
System.out.println("Cat init");
}
public void destroy() {
System.out.println("Cat destroy");
}
}
config配置类:
//指定Cat对象中哪个方法作为 初始化方法 和 销毁方法
@Bean(initMethod = "init",destroyMethod = "destroy")
public Cat cat() {
return new Cat();
}
调用:
@Test
public void test02() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config2.class);
System.out.println("容器初始化完成……");
context.close();
}
输出:
Cat constructor
Cat init
容器初始化完成……
Cat destroy
以上是单例bean:
如果在config中配置:@Scope(“prototype”)
调用:
public void test02() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config2.class);
System.out.println("容器初始化完成……");
//多实例bean只有调用的时候才会初始化bean
context.getBean("cat");
context.close();
}
输出:
容器初始化完成……
Cat constructor
Cat init
多实例bean中,容器只负责创建,不会进行管理,所以不会调用销毁方法
实现 InitializingBean 和 DisposableBean
通过实现 InitializingBean 和 DisposableBean接口来实现afterPropertiesSet()初始化方法 和 destroy()销毁方法
pojo改进:
public class Cat implements InitializingBean , DisposableBean {
public Cat() {
System.out.println("Cat constructor");
}
public void init() {
System.out.println("Cat init");
}
//实现DisposableBean接口会有destroy()方法,所以原来的destroy()要加上@Override注解
@Override
public void destroy() {
System.out.println("Cat destroy");
}
//在属性赋值之后执行,即构造方法执行之后
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Cat afterPropertiesSet");
}
}
输出:
Cat constructor
Cat afterPropertiesSet
Cat init
容器初始化完成……
Cat destroy
使用JSR250
通过使用 @PostConstruct 和 @PreDestroy 标注方法上来指定初始化和销毁方法
@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
pojo改进:
public class Cat implements InitializingBean , DisposableBean {
public Cat() {
System.out.println("Cat constructor");
}
@PostConstruct
public void preinit(){
System.out.println("Cat preinit");
}
public void init() {
System.out.println("Cat init");
}
@PreDestroy
public void predestroy() {
System.out.println("Cat predestroy");
}
@Override
public void destroy() {
System.out.println("Cat destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Cat afterPropertiesSet");
}
}
输出:
Cat constructor
Cat preinit
Cat afterPropertiesSet
Cat init
容器初始化完成……
Cat predestroy
Cat destroy
通过实现BeanPostProcessor-后置处理器
通过实现BeanPostProcessor接口的postProcessBeforeInitialization() 和 postProcessAfterInitialization()方法。
BeanPostProcessor: bean的后置处理器【在bean初始化前后进行一些处理工作】
postProcessBeforeInitialization: 在初始化之前工作
postProcessAfterInitialization: 在初始化之后工作
实现BeanPostProcessor接口:
@Component//加入到ioc容器
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization。。。" + beanName + "===>" + bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization。。。" + beanName + "===>" + bean);
return bean;
}
}
输出:
postProcessBeforeInitialization。。。config2===>com.lly.Config.Config2$$EnhancerBySpringCGLIB$$3f1d8000@4b5a5ed1
postProcessAfterInitialization。。。config2===>com.lly.Config.Config2$$EnhancerBySpringCGLIB$$3f1d8000@4b5a5ed1
postProcessBeforeInitialization。。。config===>com.lly.Config.Config$$EnhancerBySpringCGLIB$$21979926@59d016c9
postProcessAfterInitialization。。。config===>com.lly.Config.Config$$EnhancerBySpringCGLIB$$21979926@59d016c9
postProcessBeforeInitialization。。。firstConreoller===>com.lly.controller.FirstConreoller@3cc2931c
postProcessAfterInitialization。。。firstConreoller===>com.lly.controller.FirstConreoller@3cc2931c
postProcessBeforeInitialization。。。secondController===>com.lly.controller.SecondController@20d28811
postProcessAfterInitialization。。。secondController===>com.lly.controller.SecondController@20d28811
postProcessBeforeInitialization。。。com.lly.pojo.Color===>com.lly.pojo.Color@3967e60c
postProcessAfterInitialization。。。com.lly.pojo.Color===>com.lly.pojo.Color@3967e60c
postProcessBeforeInitialization。。。person===>Person{id='1', name='zs', age=18}
postProcessAfterInitialization。。。person===>Person{id='1', name='zs', age=18}
postProcessBeforeInitialization。。。myFactoryBean===>com.lly.Config.MyFactoryBean@22a637e7
postProcessAfterInitialization。。。myFactoryBean===>com.lly.Config.MyFactoryBean@22a637e7
Cat constructor
postProcessBeforeInitialization。。。cat===>com.lly.pojo.Cat@4c9f8c13
Cat preinit
Cat afterPropertiesSet
Cat init
postProcessAfterInitialization。。。cat===>com.lly.pojo.Cat@4c9f8c13
容器初始化完成……
Cat predestroy
Cat destroy
在初始化方法的前后执行;无论是否有初始化和方法,他都会执行
BeanPostProcessor原理
可以在自定义的BeanPostProcessor中打一个断点,直接debug。
//给bean进行属性赋值
this.populateBean(beanName, mbd, instanceWrapper);
//BeanPostProcessor的执行在初始化bean方法内部
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
initializeBean:
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//执行自定义初始化方法
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
applyBeanPostProcessorsBeforeInitialization:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
原理:
遍历得到容器中所有的BeanPostProcessors;然后挨个执行postProcessBeforeInitialization,
一旦返回null,跳出for循环,不会执行后面的BeanPostProcessors.postProcessBeforeInitialization
BeanPostProcessor在Spring底层的使用
执行时机:
-doCreateBean
-populateBean():给bean的各种属性赋值
-initializeBean():初始化bean
-处理Aware方法
-applyBeanPostProcessorsBeforeInitialization:后置处理器的实例化前拦截
-invokeInitMethods:执行@Bean指定的initMethod
-applyBeanPostProcessorsAfterInitialization:后置处理器的实例化后拦截
应用:
-BeanValidationPostProcessor 用来实现数据校验
-AutowireAnnotationBeanPostProcessor, @Autowire实现(即怎么知道某个类标注了@Autowire注解)
-ApplicationContextProcessor 实现XXXAware的自动注入。
等。。。。
都有使用到BeanPostProcessor
通过实现ApplicationContextAware接口来实现保存applicationContext容器信息:
给Cat类中定义一个成员变量applicationContext,然后实现ApplicationContextAware接口,
再实现setApplicationContext方法,在方法中可以获取到ioc容器ApplicationContext applicationContext,
再通过this.applicationContext=applicationContext给Cat类中保存ioc容器信息
public class Cat implements InitializingBean , DisposableBean, ApplicationContextAware {
------省略一点内容---------
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
}