你可能在学习其他框架的时候,听到过“生命周期”的概念,通常,框架会提供给你回调方法,在生命周期的关键点,框架会调用这些回调方法。比如你给你的小程序或者安卓应用编写页面的时候,会有类似onHide()、onShow()这种方法,分别在显示(show)页面或者离开(hide)页面的时候调用到,他们正属于页面生命周期的一部分。
在Spring容器中的对象(Bean),也有着自己的生命周期,只不过比较简单一点,因为只有两个关键点。第一个关键点是Bean的所有依赖都已经装配好的时候,另一个是容器即将销毁的时候。你可能会问,容器什么时候销毁?如果你不是自己维护ApplicationContext
的话,而是框架自动维护的话,比如使用Spring Boot写web运用,那么你程序停止运行的时候,就是容器销毁的时候。这个时候容器中的对象会根据自己的情况,来释放一些资源,比如关闭它跟外部系统的一些连接等。
这两个关键点的回调,有多种方式可以实现:
- 实现
InitializingBean
和DisposableBean
接口 - 使用
@PostConstruct
和@PreDestroy
注解 - 为
@Bean
注解添加initMethod
和destroyMethod
参数


InitializingBean
和DisposableBean
接口分别提供了afterPropertiesSet
和destroy
方法。@PostConstruct
和@PreDestroy
注解可以分别放到你对象的方法上,这样在回调的时候,添加了注解的方法就会被调用到。@Bean
的initMethod
和destroyMethod
参数是String类型的,你可以将方法的名字传递进去。

从上面这些英文单词的意思中你会意识到,他们其实完成的工作,就是初始化和释放资源的工作。Spring官方文档里说了,不建议使用InitializingBean
和DisposableBean
,因为他们跟Spring耦合到了一起,不方便以后更换其他IoC容器,而是建议使用@PostConstruct
和@PreDestroy
注解,毕竟他们是标准,是JSR-250的一部分。要我说呀,我既然都选择Spring全家桶了,既然都选择Spring Boot了,我还可能去更换IoC容器么?不可能了呀,所以这两种方式都可以用的,我更倾向于用接口。

@Bean
有initMethod
和destroyMethod
参数,传递的是方法名,这种做法非常不“type-safe”,感觉更像是对以前xml配置方式的兼容。然而他还是有用的,有些Bean并不是由你自己编写的,比如从某个jar包里拿出来的,你不能再去修改类了,只能从外部来设置回调。
我建议你始终保持风格的统一,比如如果你用了InitializingBean
,那就在项目里保持一致,都用它。如果实在是不行,也就是说你用到了多种方法,那么你可能需要注意下他们顺序,初始化回调的顺序是:
@PostConstruct
InitializingBean
@Bean
的initMethod参数对应方法
在销毁时,顺序跟上面是一致的:
@PreDestroy
DisposableBean
@Bean
的destroyMethod参数对应方法
另外值得一提的是,Spring框架有很多*Aware
结尾的接口,常见的比如ApplicationContextAware
和BeanNameAware
,如果你的@Component
类实现了ApplicationContextAware
,那么容器会调用他的setApplicationContext方法,这样你就可以得到ApplicationContext
对象了,你可以拿这个对象查找一些Bean呀等等。同理你可以通过BeanNameAware
的setBeanName方法来获取Bean的名字。
还有其他一些*Aware
结尾的接口,用的不太多。aware单词的意思是“意识到的、知道的”,*Aware
目标就是为了让你的类能“意识到、感觉到”框架里的某些东西。*Aware
接口的方法会在对象装配完成之后执行,但是会在@PostConstruct
等初始化方法执行之前。如果你是一个业务程序员,或者说CRUD程序员,我不建议你使用*Aware
,因为在这种做法将你的对象和Spring容器的细节绑定在一起。如果你是为了给项目写一些基础工具,或者中间件等,倒是可以用用。
我读了很多网上关于Bean生命周期的文章,很多都画了复杂的流程图,如果你碰巧也看过,可以得知,总的流程也就是:装配完=>*Aware
执行=>初始化=>用=>销毁。其实很简单是不是?如果你深究,还会发现有很多需要挖掘的东西(比如BeanPostProcessor
等),不过由于源码太博大精深,我只能先暂停,补一补知识漏洞再来。
注意:本文归作者所有,未经作者允许,不得转载