前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Bean 生命周期之“我从哪里来”?懂得这个很重要

Spring Bean 生命周期之“我从哪里来”?懂得这个很重要

作者头像
用户4172423
发布2019-09-04 14:42:07
7460
发布2019-09-04 14:42:07
举报
文章被收录于专栏:日拱一兵日拱一兵

Spring bean 的生命周期很容易理解。实例化 bean 时,可能需要执行一些初始化以使其进入可用 (Ready for Use)状态。类似地,当不再需要 bean 并将其从容器中移除时,可能需要进行一些清理,这就是它的生命周期

上一篇文章 面试还不知道BeanFactory和ApplicationContext的区别? 中说明了接口 Beanfactory 和 ApplicationContext 可以通过 T getBean(String name, Class<T> requiredType) 方法从 Spring 容器中获取bean,区别是,前者是懒加载形式,后者是预加载的形式。那么问题来了:

这些 Spring Beans 是怎么生成出来的呢?

在正式回答这个问题之前,先解答一些有关 Java Bean, Spring Bean 和 Spring IoC 容器这些概念性的疑惑,我希望通过下面这个例子形象说明这些问题:

小学生 (Java Bean)通过提交资料申请(元数据配置)加入了少先队(Spring Ioc 容器),学习了一些精神与规定之后,变成了少先队员(Spring Bean)

从这里可以看出,Java Bean 和 Spring Bean 都是具有特定功能的对象,小学生还是那个小学生,只不过加入了少先队之后有了新的身份,新的身份要按照组织 (Spring Ioc)的规定履行特定义务

来看下图加深一下了解

首先要有容器,实例化 Spring Ioc 容器是非常简单的,接口 org.springframework.context.ApplicationContext表示Spring IoC容器,负责实例化,配置和组装上述 bean。容器通过读取配置元数据获取有关要实例化,配置和组装的对象的指令。配置元数据通常以XML,Java 注解或代码的形式表示。它允许你自己表达组成应用程序的对象以及这些对象之间丰富的相互依赖性,比如这样:

代码语言:javascript
复制
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring.xml", "spring1.xml"});

有了容器,我们需要做哪些处理,使其内部对象变为 Ready for Use 的状态?

我们需要通过 Spring 容器实例化它们,Spring 为我们提供了三种方式:

三种初始化方式

InitializingBean

Spring 为我们提供了 InitializingBean 接口

代码语言:javascript
复制
public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

我们可以通过实现 InitializingBean 接口,在其唯一方法 afterPropertiesSet 内完成实例化的工作,但是 Spring Framework 官方并不建议我们通过这种方法来完成 Bean 的实例化,这是一种强耦合的方式,我们看到框架层面才会用到这个方法。

@PostConstruct

这种方式是 Spring 非常提倡的一种方式,我们通常将其标记在方法上即可,通常习惯将这个方法起名为 init()

代码语言:javascript
复制
@PostConstruct
public void init() {
  System.out.println("Inside init() method...");
}

init-method

你应该见过这种初始化方式:

代码语言:javascript
复制
public class MyClass {
   public void init() {
      // perform post-creation logic here
   }
}

@Configuration
public class AppConfig {
   @Bean(initMethod = "init")
   public MyClass myclass() {
      return new MyClass ();
   }
}

你也应该见过这种配置方式:

代码语言:javascript
复制
<bean id="myClass" class="com.demo.MyClass" init-method="init"/>

没错,这只是同样功能的不同实现方式罢了以上就是三种初始化 Spring Beans 的方式,我们在框架中看到过三种方式在组合使用,那么组合使用的调用顺序是什么呢?

  1. 首先@PostConstruct 会被最先调用
  2. 其次 InitializingBean.afterPropertiesSet()方法将会被调用
  3. 最后调用通过 XML 配置的 init-method 方法或通过设置 @Bean 注解 设置 initMethod 属性的方法

了解了这些,你也就了解了 Spring Bean 是怎么来的了

通过图示来说明一下:

组合使用,这个调用顺序很难记忆吗吗?

PostConstruct (P),afterPropertiesSet (A),init-method (I) ---> PAI (圆周率π)

BeanPostProcessor

BeanPostProcessor 接口,大家也应该有印象,里面只有两个方法:

代码语言:javascript
复制
public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;

    Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}

看方法名,BeforeInitialization 和 AfterInitialization,我们应该猜得出,这是在上述三种方式的前和后,算是一种全局的切面思想,我们经常会使用 postProcessAfterInitialization方法,通过读取 Bean 的注解完成一些后续逻辑编写与属性的设定,现在 Ready for Use之前是这样:

Ready for Use 之前,了解这些内容,已可以基本满足日常的工作内容,但这并不是 Ready for Use 的全部内容,Spring Bean 整个生命周期的流程应该是这样的,后续文章会逐步点亮:

灵魂追问

  1. 了解了 Spring Bean 是怎么来的?那它是怎么没的呢?什么时候需要销毁他们呢?
  2. Spring 框架中 XxxxAware,这些类有什么作用,能在 Ready for Use 之前有用处吗?
  3. 你日常的工作中有充分利用今天说明的这些内容吗?懂得这些会大大方便你的编程

带着疑问去思考,然后串联,进而归纳总结,不断追问自己,进行自我辩证,像侦查嫌疑案件一样看待技术问题,漆黑的街道,你我一起寻找线索,你就是技术界大侦探福尔摩斯

补充说明

  1. 虽然当下流行以注解声明方式进行编程,甚至高版本 Spring 会将一些方法标记为过时,但文章说明依旧会使用 XMLBeanFactory 这类方法,包括 XML 配置。这样做,只不过为了更清晰的说明问题。
  2. 另外将 Spring Bean 生命周期系列的讲解,进行拆分,是为了让大家有独立的思考空间,带着问题去思考、实践,而不是被动的填充,最终串联起自己的学习网络,这样理解的更深刻,具体请看之前写的文章 程序猿为什么要看源码, 后续内容请持续关注

欢迎持续关注公众号:「日拱一兵」,后续会出一系列文章点亮 Spring Bean 周期图,以完整代码示例说明这个周期的调用顺序;同时进行 Spring 知识点解释与串联,轻松搞定面试那点事,以及在工作中充分利用 Spring 的特性


PlantUML

Plant UML 是 IntelliJ IDEA 的一个插件,在 IDE 里,可以快速的画 UML 图,如果你有画图需求要做,这是一个很好的选择

  • Sequence diagram
  • Usecase diagram
  • Class diagram
  • Activity diagram (here is the legacy syntax)
  • Component diagram
  • State diagram
  • Object diagram
  • Deployment diagram
  • Timing diagram
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 日拱一兵 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 三种初始化方式
    • InitializingBean
      • @PostConstruct
        • init-method
        • BeanPostProcessor
        • 灵魂追问
        • 补充说明
          • PlantUML
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档