转载

Spring Boot教程(22) – 容器中对象的生命周期

你可能在学习其他框架的时候,听到过“生命周期”的概念,通常,框架会提供给你回调方法,在生命周期的关键点,框架会调用这些回调方法。比如你给你的小程序或者安卓应用编写页面的时候,会有类似onHide()、onShow()这种方法,分别在显示(show)页面或者离开(hide)页面的时候调用到,他们正属于页面生命周期的一部分。

在Spring容器中的对象(Bean),也有着自己的生命周期,只不过比较简单一点,因为只有两个关键点。第一个关键点是Bean的所有依赖都已经装配好的时候,另一个是容器即将销毁的时候。你可能会问,容器什么时候销毁?如果你不是自己维护 ApplicationContext 的话,而是框架自动维护的话,比如使用Spring Boot写web运用,那么你程序停止运行的时候,就是容器销毁的时候。这个时候容器中的对象会根据自己的情况,来释放一些资源,比如关闭它跟外部系统的一些连接等。

这两个关键点的回调,有多种方式可以实现:

  1. 实现 InitializingBeanDisposableBean 接口
  2. 使用 @PostConstruct@PreDestroy 注解
  3. @Bean 注解添加 initMethoddestroyMethod 参数
Spring Boot教程(22) – 容器中对象的生命周期
InitializingBean
Spring Boot教程(22) – 容器中对象的生命周期
DisposableBean

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

Spring Boot教程(22) – 容器中对象的生命周期
方法名可以自定义

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

Spring Boot教程(22) – 容器中对象的生命周期
Intellij IDEA中可以方便地跳转到方法

@BeaninitMethoddestroyMethod 参数,传递的是方法名,这种做法非常不“type-safe”,感觉更像是对以前xml配置方式的兼容。然而他还是有用的,有些Bean并不是由你自己编写的,比如从某个jar包里拿出来的,你不能再去修改类了,只能从外部来设置回调。

我建议你始终保持风格的统一,比如如果你用了 InitializingBean ,那就在项目里保持一致,都用它。如果实在是不行,也就是说上面说到的三种方法都用了,那么你可能需要注意下他们顺序,初始化回调的顺序是:

@PostConstruct
InitializingBean
@Bean

在销毁时,顺序跟上面是一致的:

@PreDestroy
DisposableBean
@Bean

另外值得一提的是,Spring框架有很多 *Aware 结尾的接口,常见的比如 ApplicationContextAwareBeanNameAware ,如果你的 @Component 类实现了 ApplicationContextAware ,那么容器会调用他的setApplicationContext方法,这样你就可以得到 ApplicationContext 对象了,你可以拿这个对象查找一些Bean呀等等。同理你可以通过 BeanNameAware 的setBeanName方法来获取Bean的名字。

还有其他一些 *Aware 结尾的接口,用的不太多。aware单词的意思是“意识到的、知道的”, *Aware 目标就是为了让你的类能“意识到、感觉到”框架里的某些东西。 *Aware 接口的方法会在对象装配完成之后执行,但是会在 @PostConstruct 等初始化方法执行之前 。如果你是一个业务程序员,或者说CRUD程序员,我不建议你使用 *Aware ,因为在这种做法将你的对象和Spring容器的细节绑定在一起。如果你是为了给项目写一些基础工具,或者中间件等,倒是可以用用。

我读了很多网上关于Bean生命周期的文章,很多都画了复杂的流程图,如果你碰巧也看过,可以得知,总的流程也就是:装配完=> *Aware 执行=>初始化=>用=>销毁。其实很简单是不是?如果你深究,还会发现有很多需要挖掘的东西(比如 BeanPostProcessor 等),不过由于源码太博大精深,我只能先暂停,补一补知识漏洞再来。

原文  https://fookwood.com/spring-boot-tutorial-22-lifecycle
正文到此结束
Loading...