Srping之Bean的初始化和销毁方法

通常,bean的初始化和销毁方法我们有三个地方可以入手,分别是:

  • 自定义初始化,销毁方法
  • 实现spring提供的InitializingBean(初始化逻辑),DisposableBean(销毁逻辑)接口
  • JSR250;@PostConstruct,@PreDestroy执行初始化和销毁方法
  • 实现spring提供的BeanPostProcessor接口,实现其postProcessBeforeInitialization方法来执行在初始化之前的操作,实现postProcessAfterInitialization方法来执行初始化之后的操作。

bean的生命周期:实例化 -> 属性赋值 -> 初始化 -> 销毁

【1】自定义初始化,销毁方法

​ 容器管理bean的生命周期:我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法

构造(对象创建):

  • 单实例:在容器启动的时候创建对象
  • 多实例:在每次获取的时候创建对象

销毁:

  • 单实例:容器关闭的时候
  • 多实例:容器不会管理这个bean;容器不会调用销毁方法,如果需要,自己手动调用销毁方法。

​ 定义一个Person类,然后定义两个方法,一个是我们想作为初始化方法的init方法,一个是我们想作为销毁方法的destory方法

public class Person {
public Person() {
System.out.println("Person...constructor");
} public void init(){
System.out.println("Person...init");
} public void destroy(){
System.out.println("Person...destroy");
}
}

​ 将Person添加到配置类当中

@Configuration
public class LifeCycleConfig { @Bean(initMethod = "init",destroyMethod = "destroy")
public Person person(){
return new Person();
}
}

​ 测试结果

public class LifeCycleConfigTest {
@Test
public void testLifeCycle(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
System.out.println("容器创建完成了...");
applicationContext.close();
}
}
/**
Person...constructor
Person...init
容器创建完成了...
Person...destroy
*/

【2】InitializingBean和DisposableBean接口

​ 我们还是在之前的Person类代码上继续编写

public class Person implements InitializingBean,DisposableBean{
public Person() {
System.out.println("Person...constructor");
} public void init(){
System.out.println("Person...init");
} public void destry(){
System.out.println("Person...destroy");
}
/**
* 当beanFactory关闭且bean为单例的对象时触发
* @throws Exception
*/
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean...Person.....destroy....");
} /**
* 当beanFactory实例化bean后,将所有的属性值设置完毕之后,才会调用该接口方法。
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean...Person.....afterPropertiesSet....");
}
}

​ 测试结果

/**
Person...constructor
InitializingBean...Person.....afterPropertiesSet....
Person...init
容器创建完成了...
DisposableBean...Person.....destroy....
Person...destroy
*/

可以看到,

  • 初始化过程:容器先调用了Person的无参构造方法来实例化Person对象实例,接着执行了InitialiaingBean的初始化方法afterPropertiesSet()方法,最后才执行我们自定义的init初始化方法。
  • 销毁过程:同样,容器也是先执行了DisposableBean的destroy方法,然后才执行了我们自定义的destry销毁方法。

【3】JSR250:@PostConstruct,@PreDestroy

  • @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法,
  • @PreDestroy:在容器销毁bean之前通知我们进行清理工作

​ 继续在上面的Person代码上修改

public class Person implements InitializingBean,DisposableBean{
public Person() {
System.out.println("Person...constructor");
} public void init(){
System.out.println("Person...init");
} public void destry(){
System.out.println("Person...destroy");
} @PostConstruct
public void PostConstruct() {
System.out.println("JSR250....PostConstruct....Person ... PostConstruct...");
} @PreDestroy
public void PreDestroy() {
System.out.println("JSR250....PreDestroy....Person ... PreDestroy...");
} /**
* 当beanFactory关闭且bean为单例的对象时触发
* @throws Exception
*/
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean...Person.....destroy....");
} /**
* 当beanFactory实例化bean后,将所有的属性值设置完毕之后,才会调用该接口方法。
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean...Person.....afterPropertiesSet....");
}
}

​ 测试结果:

/**
Person...constructor
JSR250....PostConstruct....Person ... PostConstruct...
InitializingBean...Person.....afterPropertiesSet....
Person...init
容器创建完成了...
JSR250....PreDestroy....Person ... PreDestroy...
DisposableBean...Person.....destroy....
Person...destroy
*/

可以看到:

  • 初始化方法的执行顺序:先执行Toyota的无参构造方法,再执行JSR250的PostConstruct初始化方法,接着执行InitializingBean的afterPropertiesSet初始化方法,最后执行我们自定义的init初始化方法。
  • 销毁方法的执行顺序:和初始化方法一样,先执行JSR250的PerDestroy销毁方法,再执行DisposableBean的destroy方法,最后执行我们自定义的destry销毁方法。

【4】实现BeanPostProcessor接口

​ BeanPostProcessor是bean的后置处理器,在bean初始化前后进行一些处理工作:

  • postProcessBeforeInitialization:在初始化之前工作

  • postProcessAfterInitialization:在初始化之后工作

    直接观察代码,会发现BeanPostProcessor的方法postProcessBeforeInitialization有返回类型Object,

postProcessAfterInitialization也有返回类型Object,同时两个方法都可以抛出BeansException异常。

​ 首先定义一个我们自己的BeanPostProcessor:

@Component
public class LifeCycleBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Person) {
System.err.println("postProcessBeforeInitialization....拦截指定bean");
}
System.out.println("这句话证明所有容器中的bean都会被postProcessBeforeInitialization拦截.. beanName=" + beanName + "==>" + bean);
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Person) {
System.err.println("postProcessAfterInitialization.....拦截指定bean");
}
System.out.println("这句话证明所有容器中的bean都会被postProcessAfterInitialization拦截.. beanName=" + beanName + "==>" + bean);
return bean;
}
}

​ 接着在配置类中添加注解包扫描:

@Configuration
@ComponentScan("com.zl")
public class LifeCycleConfig { @Bean(initMethod = "init",destroyMethod = "destry")
public Person person(){
return new Person();
}
}

​ 测试结果:

第一个标示点:说明所有容器加载的bean在实例化之后,初始化之前都会执行postProcessBeforeInitialization方法,在初始化完成后执行postProcessAfterInitialization方法。

第二个标示点:说明我们可以只拦截我们指定的bean,并且执行的顺序是:

  • 1.容器对bean进行实例化
  • 2.初始化前执行自定义BeanPostProcessor的postProcessBeforeInitialization方法
  • 3.如果存在JSR250的初始化方法,则执行其初始化方法
  • 4.如果实现了InitializingBean接口,则执行其afterPropertiesSet方法
  • 5.如果存在我们自定义的初始化方法(initMethod),则执行自定义初始化方法
  • 6.初始化方法结束后,执行自定义BeanPostProcessor的postProcessAfterInitialization方法。
  • 7.容器关闭时,若存在JSR250的销毁方法,则先调用JSR250的销毁方法
  • 8.若实现了DisposableBean接口,则调用其destroy方法
  • 9.最后,若存在我们自定义的销毁方法(destroyMethod),则执行我们自定义的销毁方法

以上九点,按顺序执行,完成bean的初始化和销毁工作。

需要注意的是,BeanPostProcessor提供的两个方法,是针对初始化前后的拦截操作,和容器的关闭,bean的销毁无关。

四、Srping之Bean的初始化和销毁的更多相关文章

  1. Spring3实战第二章第一小节 Spring bean的初始化和销毁三种方式及优先级

    Spring bean的初始化和销毁有三种方式 通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法: 优先级第二通过 <bean& ...

  2. Spring Boot实战笔记(三)-- Spring常用配置(Bean的初始化和销毁、Profile)

    一.Bean的初始化和销毁 在我们的实际开发的时候,经常会遇到Bean在使用之前或之后做些必要的操作,Spring对Bean的生命周期操作提供了支持.在使用Java配置和注解配置下提供如下两种方式: ...

  3. spring boot之 Bean的初始化和销毁(4)

    原文:https://blog.csdn.net/z3133464733/article/details/79189699 -------------------------------------- ...

  4. 12、生命周期-@Bean指定初始化和销毁方法

    12.生命周期-@Bean指定初始化和销毁方法 Bean的生命周期:创建->初始化->销毁 容器管理bean的生命周期 我们可以自定义初始方法和销毁方法,容器在bean进行到当期那生命周期 ...

  5. 【Spring Framework】Spring注解设置Bean的初始化、销毁方法的方式

    bean的生命周期:创建---初始化---销毁. Spring中声明的Bean的初始化和销毁方法有3种方式: @Bean的注解的initMethod.DestroyMethod属性 bean实现Ini ...

  6. Spring bean 实现初始化、销毁方法的方式及顺序

    Spring 允许 Bean 在初始化完成后以及销毁前执行特定的操作,常用方法有三种: 使用注解,在指定方法上加上@PostConstruct或@PreDestroy注解来制定该方法是在初始化之后还是 ...

  7. spring bean的初始化以及销毁

    spring bean初始化或销毁时执行某些方法,有很多使用场景.比如初始化时,启动bean中的线程池.销毁时释放资源,个人比较喜欢实现InitializingBean和 DisposableBean ...

  8. Spring bean的初始化及销毁

    Spring bean的几个属性:scope.init-method.destroy-method.depends-on等. Scope 在Spring容器中是指其创建的Bean对象相对于其他Bean ...

  9. @Bean 指定初始化和销毁方法

    bean 的生命周期 bean 的创建 --> 初始化 --> 销毁 ioc 容器管理 bean 的声明周期 可以自定义初始化和销毁方法 构造器( 对象创建 )被调用时机 单实例:在容器启 ...

随机推荐

  1. D3力布图绘制--节点自己连自己的实现

    案例分析 先看下实现的效果图 实现方法 本篇是在之前写的博文 D3力布图绘制--节点间的多条关系连接线的方法 基础上加修改的,这里放上修改的代码,其他的一样 // DATA var nodes = [ ...

  2. Linux常用命令之重启关机命令

    shutdown命令 shutdown命令用来系统关机命令.shutdown指令可以关闭所有程序,并依用户的需要,进行重新开机或关机的动作. 实例 指定现在立即关机: shutdown -h now ...

  3. 2019_JAVA面试题_真实总结

    来自刚被某互联网公司录取的朋友的分享. 整理的面试题1: 1.Java里面有哪几种基础数据类型, 2.Char为何是两个字节, 3.Object有哪些方法 4.final修饰变量,函数,类的作用, 5 ...

  4. 故事2:.net程序员成长经历

    啊,最近一段时间在学习asp.net mvc ,一直没有接着写了,加上白天工作很忙,每天都很辛苦的哈,那咱接着说上一个故事哈. 当时第二天开始复习java面试题,非常的期待,从来没有去过公司,不知道别 ...

  5. python:王思聪究竟上了多少次热搜?

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 朱小五 凹凸玩数据 PS:如有需要Python学习资料的小伙伴可以加 ...

  6. Dynamics CRM使用元数据之一:查询实体的主字段(托管代码版本)

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复159或者20151013可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! Dynamics CRM是基于元 ...

  7. form分辨率

    近期做项目时,遇到开发的winform在自己电脑上可以正常显示,共享到其他电脑就事儿不能显示了: [转载自:http://blog.csdn.net/lcawen88/article/details/ ...

  8. 工具类Base64Util

    在和服务器交互的过程中,有时候我们需要把图片编码成base64字符串传输,记录一下工具类 import android.graphics.Bitmap; import android.graphics ...

  9. hadoop 自定义OutputFormat

    1.继承FileOutputFormat,复写getRecordWriter方法 /** * @Description:自定义outputFormat,输出数据到不同的文件 */ public cla ...

  10. 【LeetCode】TreeNode类实现解析(java实现)

    https://blog.csdn.net/styshoo/article/details/52865386 在LeetCode中,TreeNode是经常用到的一个结构体,表示数据结构树(Tree)中 ...