Bean 创建出来之后,就会涉及到Bean的生命周期的问题了,
1.生命周期的意义
1.1生命周期的阶段
一个对象从被创建,到被垃圾回收,可以宏观的划分为 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
@Component
public class Pen implements InitializingBean, DisposableBean {
private Integer ink;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("钢笔中已加满墨水。。。");
this.ink = 100;
}
@Override
public void destroy() throws Exception {
System.out.println("钢笔中的墨水都放干净了。。。");
this.ink = 0;
}
@Override
public String toString() {
return "Pen{" + "ink=" + ink + '}';
}
}
2.4 SpringFramework中控制Bean生命周期的三种方式
以下的对比维度不是最终最全的,不过在现在的阶段已经是足够了:
init-method & destroy-method | @PostConstruct & @PreDestroy | InitializingBean & DisposableBean | |
---|---|---|---|
执行顺序 | 最后 | 最先 | 中间 |
组件耦合度 | 无侵入(只在 |
与 JSR 规范耦合 | 与 SpringFramework 耦合 |
容器支持 | xml 、注解原生支持 | 注解原生支持,xml需开启注解驱动 | xml 、注解原生支持 |
单实例Bean | √ | √ | √ |
原型Bean | 只支持 init-method | √ | √ |