五)Bean 的生命周期,创建---初始化---销毁的过程
目录
三,实现 InitializingBean 接口的 afterPropertiesSet()方法,当beanFactory 创建好对象,且把bean所有属性设置好之后,相当于初始化方法。
实现 DisposableBean 的destory(),方法 当bean销毁时,会把单例bean 进行销毁
四, 可以使用JSR250规则定义的(java规范)两个注解来实现,JDK自带
五,Bean 的后置处理器,在 Bean 初始化之前调用进行拦截,在 bean 初始化前后进行一些处理工作,使用BeanPostProcessors 控制 Bean的生命周期。
一 , 指定初始化方法 init-method 方法
- 单实例 Bean,可以正常调用初始化和销毁方法
- 多实例的 Bean,容器只负责初始化,但不会管理bean,容器关闭时不会调用销毁方法
示例代码:===》 项目 源码 ====》 Cap8包: xml 方式 指定
<!--创建Bike 类 bike 实例, 自定义初始化方法 init(),自定义销毁方法 destory()-->
<bean id="bike" class="com.enjoy.Cap8.bean.Bike" init-method="init" destroy-method="destory"></bean>
注解实现===》项目 源码 ====》 Cap8包: (单实例模式下在容器创建之前实例化 Bean )
//自定义初始化方法, 销毁方法
@Bean(initMethod = "init",destroyMethod = "destory")
public Bike bike(){
System.out.println("公交车到站了====》注册到bean");
return new Bike();
}
public class Bike {
public Bike(){
System.out.println("有一位乘客上车了=====>调类的构造方法");
}
//自定义bean 初始化方法
public void init(){
System.out.println("车启动了====》 bean初始化方法");
}
//自定义bean 销毁方法
public void destory(){
System.out.println("车爆炸了====》bean销毁方法,关闭容器");
}
}
测试结果:
@Test
public static void main(String[] args){
//创建上下文对象
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
app.close();
}
注解实现===》项目 源码 ====》 Cap8包(多实例,容器在创建之前 不会去实例化 Bean ,只有当 getBean() 的时候才会去 创建实例 )
//自定义初始化方法, 销毁方法,多实例模式下
@Scope("prototype")
@Bean(initMethod = "init",destroyMethod = "destory")
public Bike bike(){
System.out.println("公交车到站了====》注册到bean");
return new Bike();
}
Bike 与上面一致 测试 :
@Test
public static void main(String[] args){
//创建上下文对象
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
System.out.println("容器创建完成");
//app.getBean("bike");
app.close();
}
当我没有去getBean 的时候, Bean 并没有实例化
@Test
public static void main(String[] args){
//创建上下文对象
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
System.out.println("容器创建完成");
app.getBean("bike");
app.close();
}
结果显而易见, 在容器创建完成之后getBean() 才会去 创建 Bean 的实例 ,并且没有调用销毁方法
实现原理: 源码跟踪
二 ,指定销毁 destory-method 方法
示例代码:见 5.1 代码 ====》项目源码 Cap8;
三,实现 InitializingBean 接口的 afterPropertiesSet()方法,当beanFactory 创建好对象,且把bean所有属性设置好之后,相当于初始化方法。
实现 DisposableBean 的destory(),方法 当bean销毁时,会把单例bean 进行销毁
示例源码: ====》项目源码 Cap8;
// 将 类注解为注解,让容器扫描注入bean
@Component
public class Volkswagen implements InitializingBean, DisposableBean {
public Volkswagen(){
System.out.println("构造方法, 大众cc,买到手");
}
//实现 DisposableBean 接口, destroy 销毁方法
@Override
public void destroy() throws Exception {
System.out.println("大众cc,没了。。===》 容器销毁");
}
//实现 InitializingBean 接口, afterPropertiesSet() 初始化方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("大众cc,最爱。。===》 bean初始化");
}
}
在配置类 增加扫描注解 将 该包下面的扫描到容器中
@Configuration
//扫描包下所有组件,并注入bean 到容器
@ComponentScan("com.enjoy.Cap8.bean")
public class Cap8MainConfigOfLifeCycle {
//自定义初始化方法, 销毁方法,多实例模式下
@Scope("prototype")
@Bean(initMethod = "init",destroyMethod = "destory")
public Bike bike(){
System.out.println("公交车到站了====》注册到bean");
return new Bike();
}
}
测试:
@Test
public static void main(String[] args){
//创建上下文对象
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
System.out.println("容器创建完成");
//System.out.println(app.getBean("bike"));
System.out.println(app.getBean("volkswagen"));
app.close();
}
四, 可以使用JSR250规则定义的(java规范)两个注解来实现,JDK自带
- @PostConstruct : 在Bean 创建完成,且shu属于赋值完成后进行初始化,属于JDK规范的注解
- @PreDestroy : 在Bean 将被移除之前进行通知,在容器销毁之前进行清理工作
示例源码: ====》项目源码 Cap8;
@Component
public class Benz {
public Benz(){
System.out.println("构造方法,买了一辆奔驰");
}
//使用JSR250规则定义 JDK 自带注解 初始化 bean
@PostConstruct
public void init(){
System.out.println("奔驰漏油了 ====》初始bean");
}
//使用JSR250规则定义 JDK 自带注解 容器销毁
@PreDestroy
public void destroy(){
System.out.println("奔驰爆炸了 ====》容器销毁");
}
}
在配置类 增加扫描注解 将 该包下面的扫描到容器中
@Configuration
//扫描包下所有组件,并注入bean 到容器
@ComponentScan("com.enjoy.Cap8.bean")
public class Cap8MainConfigOfLifeCycle {
//自定义初始化方法, 销毁方法,多实例模式下
@Scope("prototype")
@Bean(initMethod = "init",destroyMethod = "destory")
public Bike bike(){
System.out.println("公交车到站了====》注册到bean");
return new Bike();
}
}
测试
@Test
public static void main(String[] args){
//创建上下文对象
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
System.out.println("容器创建完成");
//System.out.println(app.getBean("bike"));
//System.out.println(app.getBean("volkswagen"));
System.out.println(app.getBean("benz"));
app.close();
}
五,Bean 的后置处理器,在 Bean 初始化之前调用进行拦截,在 bean 初始化前后进行一些处理工作,使用BeanPostProcessors 控制 Bean的生命周期。
实现 BeanPostProcessors两个接口即可:
- postProcessBeforelnitialization() 在Bean 初始化之前 进行拦截 增强
- postProcessAfterInitalization() 在Bean 初始化之后 进行拦截 增强
Spring 底层对 BeanPostProcessor 的使用,包括 bean 的赋值,注入其他组件,生命周期注解功能等。 如:
- ApplicationContextAwareProcesspor 接口 这个后置处理器其实就是判断我们的 bean 有没有实现 ApplicationContextAware 这个接口 ,并处理相应的逻辑,
- BeanValidationPostProcess 接口 数据校验
- InitDestroyAnnotationBeanPostProcessor 接口 此处理器 是用来处理 上述 5.4@PostConstruct @PreDestroy 让 容器 找到 init 方法 和 destroy 方法
示例源码: ====》项目源码 Cap8;
实现 BeanPostProcessors 接口, 里面的两个方法
@Component
public class Bmw implements BeanPostProcessor {
/**Aop 在初始化bean 拦截 进行增强 做一些操作,如 任何bean 初始化回调或自定义初始化方法之前,
*将此BeanPostProcessor应用于给定的新bean实例 bean已经填充了属性值。 返回的bean实例可能是原始实例的包装器
**/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization=====>"+bean+"===>"+beanName);
return bean;
}
/**Aop 在初始化bean 拦截 进行增强 做一些操作,如 一般的Aop 事务 在事件之后 commit,
*在bean初始完后 拦截 增强 对于FactoryBean,将为FactoryBean 实例和FactoryBean创建的对象调用此回调。
* 处理器可以通过相应的检查来决定是应用于FactoryBean还是应用于创建的对象。 与所有其他BeanPostProcessor回调相比
**/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization=====>"+bean+"===>"+beanName);
return bean;
}
}
配置类 ; 为了便于观察 当前 只是 扫描到 benz 这个类
@Configuration
//扫描包下所有组件,并注入bean 到容器
@ComponentScan("com.enjoy.Cap8.bean")
public class Cap8MainConfigOfLifeCycle {
//自定义初始化方法, 销毁方法,多实例模式下
//@Scope("prototype")
//@Bean(initMethod = "init",destroyMethod = "destory")
public Bike bike(){
System.out.println("公交车到站了====》注册到bean");
return new Bike();
}
}
测试:
@Test
public static void main(String[] args){
//创建上下文对象
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap8MainConfigOfLifeCycle.class);
System.out.println("容器创建完成");
//System.out.println(app.getBean("bike"));
//System.out.println(app.getBean("volkswagen"));
System.out.println(app.getBean("benz"));
app.close();
}
观察结果
六 :项目Demo
Spring源码深度解析,(附代码示例 码云地址: https://gitee.com/Crazycw/SpringCode.git)
参考资料: https://docs.spring.io/spring/docs/4.3.18.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/
请看下篇: Spring源码深度解析,初始Spring源码(六)(附代码示例:)