视频地址:https://www.bilibili.com/video/BV1oW41167AV
对应代码Git库地址:https://github.com/whh306318848/spring-annotation.git
- Bean的生命周期是指Bean的创建–初始化–销毁的过程,Bean的生命周期是由容器来管理的
- 关于构造(对象创建),单实例Bean是在容器启动的时候进行创建的,而多实例Bean是在每次获取的时候才进行创建的
- 关于初始化,初始化代码是在对象创建完成并赋值之后进行调用的
- 关于销毁,单实例Bean是在容器关闭的时候(即容器的close方法被调用时)进行销毁的,而多实例Bean的销毁工作容器不会进行管理
- 我们可以自定义Bean的初始化和销毁方法,容器会在Bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
- 自定义Bean的初始化和销毁共有四种方法,分别是
– 指定初始化和销毁方法
– 让Bean实现InitializingBean、DisposableBean接口定义
– 使用@PostConstruct注解和@PreDestroy注解
– 自定义类实现BeanPostProcessor接口
7. 第一种,指定初始化和销毁方法有两种方式实现
7.1. 在bean的xml配置文件中,可以为bean标签添加init-method和destory-method属性指定初始化和销毁方法,这两个方法必须没有参数,但是可以抛出异常,以上两个方法必须定义在当前对象的类里
7.2. 除了xml配置文件外,也可以使用注解的方式设置Bean的初始化和销毁方法,可以在@Bean注解中设置initMethod和destroyMethod,其值就是对应方法的方法名,以上两个方法必须定义在当前对象的类里
public class Car {
public Car() {
System.out.println("car constructor...");
}
public void init() {
System.out.println("car init...");
}
public void destory() {
System.out.println("car destory...");
}
}
@Bean(initMethod = "init", destroyMethod = "destory")
public Car car() {
return new Car();
}
- 第二种,可以通过让Bean实现InitializingBean接口的afterPropertiesSet方法和DisposableBean接口的destroy方法实现自定义初始化和销毁
@Component
public class Cat implements InitializingBean, DisposableBean {
public Cat() {
System.out.println("cat constructor...");
}
/***
* @Author: wuhaohua
* @Date: 2020/12/29
* @Description: 在Bean销毁之前被调用
**/
@Override
public void destroy() throws Exception {
System.out.println("cat destroy...");
}
/***
* @Author: wuhaohua
* @Date: 2020/12/29
* @Description: 在Bean构建之后,初始化之前被调用
**/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("cat afterPropertiesSet...");
}
}
- 第三种,可以使用JSR250规范中定义的两个注解:@PostConstruct和@PreDestroy
9.1. @PostConstruct:在Bean装配完成后,即对象创建,属性赋值完成后,执行初始化,是一个标注在方法上的注解
9.2. @PreDestroy:在容器销毁bean之前,通知我们进行清理工作
@Component
public class Dog {
private ApplicationContext applicationContext;
public Dog() {
System.out.println("dog constructor...");
}
/***
* @Author: wuhaohua
* @Date: 2020/12/29
* @Description: 对象创建并赋值之后调用
**/
@PostConstruct
public void init() {
System.out.println("dog PostConstruct...");
}
/***
* @Author: wuhaohua
* @Date: 2020/12/29
* @Description: 容器移除对象之前调用
**/
@PreDestroy
public void destory() {
System.out.println("dog PreDestroy...");
}
}
- 第四种,实现BeanPostProcessor接口,即bean的后置处理器,是在bean初始化前后进行一些处理工作,该接口定义了两个方法,分别是postProcessBeforeInitialization(在已经创建Bean实例之后,在任何初始化方法调用之前被调用)和postProcessAfterInitialization(在Bean实例的初始化之后被调用)
10.1. postProcessBeforeInitialization方法有两个参数,分别是bean(刚创建的实例)和beanName(该实例在容器中的名字),其返回值是后面要用的bean实例,即可返回原来的对象,也可以返回包装后的对象
10.2. postProcessAfterInitialization方法有两个参数,分别是bean(刚创建的实例)和beanName(该实例在容器中的名字),即可返回原来的对象,也可以返回包装后的对象
/**
* @author: wuhaohua
* @date: Created in 2020/12/29 18:02
* @description: 后置处理器:初始化前后进行处理工作
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
/***
* @param bean 刚创建的实例
* @param beanName 这个实例在容器中的名字
* @return 将要使用的bean实例
* @Author: wuhaohua
* @Date: 2020/12/29
* @Description:
**/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization..." + beanName + "=>" + bean);
return bean;
}
/***
* @param bean 刚创建的实例
* @param beanName 这个实例在容器中的名字
* @return 将要使用的bean实例
* @Author: wuhaohua
* @Date: 2020/12/29
* @Description:
**/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization..." + beanName + "=>" + bean);
return bean;
}
}
10.3. BeanPostProcessor的工作原理:
// 给bean进行属性赋值
populateBean(beanName, mbd, instanceWrapper);
initializeBean {
// 找到所有的BeanPostProcessor,遍历,然后执行其postProcessBeforeInitialization方法,一旦某个postProcessBeforeInitialization返回null以后,后面的BeanPostProcessor就不会被执行了,整个方法就直接返回了
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 执行自定义初始化函数
invokeInitMethods(beanName, wrappenBean, mbd);
//
applyBeanPostProcessAfterInitialization(wrappedBean, beanName);
}
- 各个方法在Bean实例化和销毁过程中的调用顺序整理
11.1. Bean实例化过程:
Bean的构造函数 > BeanPostProcessor的postProcessBeforeInitialization() > @PostConstruct注解标注的方法 > InitializingBean的afterPropertiesSet() > Bean的initMethod() > BeanPostProcessor的postProcessAfterInitialization()
11.2. Bean销毁过程:
@PreDestroy注解标注的方法 > DisposableBean的destroy() > Bean的destroyMethod() -
BeanPostProcessor在Spring底层的使用
12.1. BeanPostProcessor有非常多的实现类,很多注解都实现了该接口
12.2. 如果组件中需要使用IOC容器,可以让组件实现ApplicationContextAware接口,该接口有一个setApplicationContext方法,其参数ApplicationContext即是IOC容器,将该方法传入的IOC容器保存起来,则该类的其他方法也可以使用这个容器
12.3. setApplicationContext方法是在当前组件被创建之后马上调用,即构造函数调用之后马上调用的
@Component
public class Dog implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Dog() {
System.out.println("dog constructor...");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
12.4. 若需要在Bean创建成功之后进行数据校验,可以通过BeanValidationPostProcessor实现
12.5. Spring底层的bean赋值、其他组件注入、@Autowired、生命周期注解功能、@Async注解等功能,都是用BeanPostProcessor实现的