Bean 创建出来之后,就会涉及到Bean的生命周期的问题了,

1.生命周期的意义

1.1生命周期的阶段

image.png
一个对象从被创建,到被垃圾回收,可以宏观的划分为 5 个阶段:

  • 创建 / 实例化阶段:此时会调用类的构造方法,产生一个新的对象
  • 初始化阶段:此时对象已经创建好,但还没有被正式使用,可能这里面需要做一些额外的操作(如预初始化数据库的连接池)
  • 运行使用期:此时对象已经完全初始化好,程序正常运行,对象被使用
  • 销毁阶段:此时对象准备被销毁,已不再使用,需要预先的把自身占用的资源等处理好(如关闭、释放数据库连接)
  • 回收阶段:此时对象已经完全没有被引用了,被垃圾回收器回收

由此可见,把控好生命周期的步骤,可以在恰当的时机处理一些恰当的逻辑。

1.2 SpringFramework 能干预的生命周期阶段

初始化, 销毁

回想一下 Servlet ,Servlet 里面有两个方法,分别叫 init 和 destroy ,咱之前在使用 Servlet 开发时,有自己调过这两个方法吗?肯定没有吧。但是这两个方法有真实的被调用过吗?肯定有吧,不然咋设计出来的呢?这两个方法都是被 Web 容器( Tomcat 等)调用的吧,用来初始化和销毁 Servlet 的。这种方法的设计思想其实就是 “回调机制” ,它都不是自己设计的,而是由父类 / 接口定义好的,由第三者(框架、容器等)来调用。回调机制跟前面咱学的那些 Aware 接口的回调注入,在核心思想上其实是一样的。

生命周期的触发,更适合叫回调,因为生命周期方法是咱定义的,但方法被调用,是框架内部帮我们调的,那也就可以称之为 “回调” 了。

2. 初始化和销毁的回调

2.1 init-method&destroy-method —-xml的参数

这里不是本文重点,不做赘述

2.2 注解方式 @PostConstruct@PreDestroy

@PostConstruct 、@PreDestroy 分别对应,初始化,和销毁的方法

2.3 实现接口的方式 InitializingBean&DisposableBean

  1. @Component
  2. public class Pen implements InitializingBean, DisposableBean {
  3. private Integer ink;
  4. @Override
  5. public void afterPropertiesSet() throws Exception {
  6. System.out.println("钢笔中已加满墨水。。。");
  7. this.ink = 100;
  8. }
  9. @Override
  10. public void destroy() throws Exception {
  11. System.out.println("钢笔中的墨水都放干净了。。。");
  12. this.ink = 0;
  13. }
  14. @Override
  15. public String toString() {
  16. return "Pen{" + "ink=" + ink + '}';
  17. }
  18. }

2.4 SpringFramework中控制Bean生命周期的三种方式

以下的对比维度不是最终最全的,不过在现在的阶段已经是足够了:


init-method & destroy-method @PostConstruct & @PreDestroy InitializingBean & DisposableBean
执行顺序 最后 最先 中间
组件耦合度 无侵入(只在 和 @Bean 中使用) 与 JSR 规范耦合 与 SpringFramework 耦合
容器支持 xml 、注解原生支持 注解原生支持,xml需开启注解驱动 xml 、注解原生支持
单实例Bean
原型Bean 只支持 init-method