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

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

frog-758072_1920.png

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

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

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

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

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

来看下图加深一下了解 Xnip2019-07-01_20-14-05.jpg框架

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

ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring.xml", "spring1.xml"});

有了容器,咱们须要作哪些处理,使其内部对象变为 Ready for Use 的状态?
咱们须要经过 Spring 容器实例化它们,Spring 为咱们提供了三种方式:post

三种初始化方式

InitializingBean

Spring 为咱们提供了 InitializingBean 接口学习

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

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

@PostConstruct

这种方式是 Spring 很是提倡的一种方式,咱们一般将其标记在方法上便可,一般习惯将这个方法起名为 init()

@PostConstruct
public void init() {
  System.out.println("Inside init() method...");
}

init-method

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

public class MyClass {
   public void init() {
      // perform post-creation logic here
   }
}

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

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

<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 是怎么来的了

经过图示来讲明一下: Xnip2019-07-01_21-46-24.jpg

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

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

BeanPostProcessor

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

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以前是这样: Xnip2019-07-02_08-38-03.jpg

Ready for Use 以前,了解这些内容,已能够基本知足平常的工做内容,但这并非 Ready for Use 的所有内容,Spring Bean 整个生命周期的流程应该是这样的,后续文章会逐步点亮: Xnip2019-07-02_08-48-24.jpg

灵魂追问

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

补充说明

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

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

推荐阅读


a (1).png

相关文章
相关标签/搜索