# Spring Bean的生命周期(一) - 概述

## 1. 如何全面理解bean的生命周期

![img](https://image.ldbmcs.com/DwjBXo.jpg)

如果这只是一个普通的 java 的对象，那这个图示完全成立、合理。不过在 SpringFramework 中，这个流程就不够完整了，我们来回忆一下前面学习的内容。

### 1.1 bean的创建之前

在 bean 的创建之前，bean 是以 `BeanDefinition` 的方式被描述和注册在 `BeanFactory` 的（准确的说是注册在 `BeanDefinitionRegistry` 中），这个时候虽然 bean 还没有被创建，但是 `BeanFactory` 中已经存有 bean 对应的 `BeanDefinition` 了，所以**在 bean 的实例化之前，还应该有** `**BeanDefinition**` **阶段**。

### 1.2 BeanDefinition的由来

`BeanDefinition` 也不是凭空出现的，要么是解析了配置文件（比如xml），要么是解析了配置类（比如`@Configuration`），要么有人编程式（注解）的注入了 `BeanDefinition` ，所以如果纵观整个 bean 的生命周期，在 `BeanDefinition` 阶段之前，还应该有 `BeanDefinition` 的来源和加载阶段。

## 2. BeanDefinition阶段的主要工作

### 2.1 BeanDefinition的来源

上面咱也说了，bean 的实例化需要先有 `BeanDefinition` 的信息，所以 `BeanDefinition` 都是怎么来的呢？这里我们来理一下。

* 声明式注入 `BeanDefinition`
* * `@Configuration` + `@Bean`

```java
@Configuration
public class QuickStartConfiguration {
    @Bean
    public Person person() {
        return new Person();
    }
}
```

* * `@Component` + `@ComponentScan`

```java
@Configuration
@ComponentScan("com.linkedbear.spring.annotation.c_scan")
public class ComponentScanConfiguration
```

* * `@Import`

```java
@Import({Boss.class, BartenderConfiguration.class})
public @interface EnableTavern
```

* 配置式注入 `BeanDefinition`
* * `<bean>` 标签声明

```xml
<bean id="person" class="com.linkedbear.spring.basic_dl.a_quickstart_byname.bean.Person"/>
```

* 编程式注入 `BeanDefinition`
* * `ImportBeanDefinitionRegistrar`

```java
public class WaiterRegistrar implements ImportBeanDefinitionRegistrar {
    
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        registry.registerBeanDefinition("waiter", new RootBeanDefinition(Waiter.class));
    }
}
```

* * 手动构造 `BeanDefinition` 注入

```java
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();

BeanDefinition personDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class)
  .addPropertyValue("name", "zhangsan").getBeanDefinition();
ctx.registerBeanDefinition("person", personDefinition);

ctx.refresh();
```

* * 借助 `BeanDefinitionRegistryPostProcessor` 注入

```java
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    registry.registerBeanDefinition("animalNameSetterPostProcessor", 
            new RootBeanDefinition(AnimalNameSetterPostProcessor.class));
}
```

通过上述的方式，就可以把 `BeanDefinition` 注入到 `BeanFactory` 中了。

### 2.2 BeanDefinition的后置处理

根据前面后置处理器学过的内容，我们可以知道 `BeanDefinition` 都构造好之后，是不会立即注册到 `BeanFactory` 的，这中间有一步执行 `BeanDefinitionRegistryPostProcessor` 的动作，等这些 `BeanDefinitionRegistryPostProcessor` 都执行完 `postProcessBeanDefinitionRegistry` 方法后，`BeanDefinition` 才会注册到 `BeanFactory` 。

![img](https://image.ldbmcs.com/IrFBsx.jpg)

这个动作之后，下一步则是执行 `BeanFactoryPostProcessor` 的 `postProcessBeanFactory` 方法了，这个阶段可以给 `BeanDefinition` 修改配置信息，添加注入的依赖项，给属性赋值等操作。

![img](https://image.ldbmcs.com/7z3JM9.jpg)

这一步执行完毕后，`BeanDefinition` 就不会再动了，`BeanDefinition` 的阶段也就算结束了。

## 3. bean实例阶段的内容

从 `AbstractApplicationContext` 的 `refresh` 方法中找到执行步骤，其中第 11 步 `finishBeanFactoryInitialization` 方法就是初始化 bean 实例的动作了：

```java
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        prepareBeanFactory(beanFactory);
        
        try {
            postProcessBeanFactory(beanFactory);
            invokeBeanFactoryPostProcessors(beanFactory);
            registerBeanPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            onRefresh();
            registerListeners();
            // 11. 初始化剩余的单实例bean
            finishBeanFactoryInitialization(beanFactory);
            finishRefresh();
        }
        // catch ......
        finally {
            resetCommonCaches();
        }
    }
}
```

这一步的动作非常多，它会将**所有还没有实例化的、非延迟加载的单实例 bean** 都创建出来。而创建一个 bean 的流程也是非常多且复杂，总体可以分为以下几个步骤。

### 3.1 BeanDefinition的合并

bean 的实例化阶段，第一步并不是直接创建对象，还记得之前的 `BeanDefinition` 合并那个特性吗？如果一个 `<bean>` 有继承另外一个 `<bean>` 定义，则会形成**父子定义**。这种情况下，创建 bean 的时候就需要读取父 bean 的定义，合并为最终的 `RootBeanDefinition` 。

### 3.2 bean的实例化

合并完 `BeanDefinition` ，下一步才是真正的实例化 bean ，不过这里要注意一个问题：如果 bean 是一个 `FactoryBean` ，这里该如何处理呢？是只创建 `FactoryBean` 本身？还是连 `FactoryBean` 创建的真实对象一起创建？

除了考虑 `FactoryBean` 之外，还有一个要考虑的因素是**缓存**问题。咱在一开始学 IOC 的由来时，就知道 `BeanFactory` 中可以缓存单实例 bean ，那么在 Spring 中是如何处理单实例 bean 在实例化后的缓存呢？

### 3.3 属性赋值+依赖注入

bean 对象实例化完成后，里面所有的成员都是空的，接下来的步骤就是属性赋值和依赖注入了。由于这部分逻辑属于 bean 实例已经创建，所以小册在这里**将该步骤划到下面的 bean 初始化部分**。

在这个环节，最重要的是如何处理 `<bean>` 中的 `<property>` 标签、bean 中的 `@Value` 、`@Autowired` 等自动注入的注解。

`BeanPostProcessor` 的扩展 `InstantiationAwareBeanPostProcessor` 可以在 bean 的实例化之后、初始化之前执行 `postProcessAfterInstantiation` 方法，以及 `postProcessProperties` ( `postProcessPropertyValues` ) 方法完成属性赋值！所以我们就可以断定，这个环节一定是 `InstantiationAwareBeanPostProcessor` 在工作。

### 3.4 bean的初始化

这个阶段相信小伙伴们都非常熟悉了，这部分就不多啰嗦了吧，后面直接翻源码看看底层原理就完事了。

### 3.5 bean的启动

之前在 bean 的生命周期中没有提到一个接口：`Lifecycle` ，之所以没有在那儿提，是考虑到 `Lifecycle` 的执行是依照 `ApplicationContext` 的生命周期而来，两者是相互关联的，所以小册把 `Lifecycle` 接口的讲解安排到了这里。

先简单说说 `Lifecycle` 的触发时机吧。往上翻一翻 `refresh` 方法的 try 块最后一行：`finishRefresh` ，它在里面会找出所有实现了 `Lifecycle` 接口的 bean ，并调用它们的 `start` 方法（所以是不是回想起了第 16 章的 `ContextStartedEvent` 事件）。注意此时所有实现了 `Lifecycle` 的非延迟加载的单实例 bean 都**已经加载完成**了，是可以正常调用 `start` 方法的。

一般实现 `Lifecycle` 的 `start` 方法多用于**建立连接**、**加载资源**等等操作，以备程序的运行期使用。

so ，这个阶段 `ApplicationContext` 就会完成所有 `Lifecycle` 类型的 bean 的 `start` 方法调用，对于一个 bean 的生命周期而言，就已经到了正常存活期了。

***

说完了 bean 的加载和初始化，当 `ApplicationContext` 关闭时，这些 bean 也是需要销毁的，而这个销毁流程我们也要来研究一下。

## 4. bean销毁阶段的内容

相比较于 bean 的创建和初始化，销毁部分就变得比较简单了，我们可以先对整个 `ApplicationContext` 的关闭有一个整体的了解。

关闭 `ApplicationContext` 会顺序执行以下几步：

1. 广播容器关闭事件

* * 学过的 `ContextClosedEvent` 事件

1. 通知所有实现了 `Lifecycle` 的 bean 回调 `close` 方法
2. 销毁所有 bean
3. 关闭 BeanFactory
4. 标记本身为不可用，

而这里面有关 bean 的销毁，就只包含 2 、3 两步，下面分述。

### 4.1 bean的停止

与上面的 bean 启动一致，如果一个 bean 实现了 `Lifecycle` 接口，此处会回调 bean 的 `close` 方法。由于此时 bean 的销毁回调方法还没有执行，所以在销毁阶段，`Lifecycle` 的执行时机是最靠前的。

一般实现 `Lifecycle` 的 `close` 方法多用来关闭连接、释放资源等操作，因为程序终止了，这些资源也就没必要持有了。

### 4.2 bean的销毁回调

bean “停止” 后，接下来就是对应于 bean 初始化阶段的三种生命周期回调的销毁部分了。不过这里面有一个不同点：`BeanPostProcessor` 的回调包含 bean 的初始化之前和初始化之后，但 `DestructionAwareBeanPostProcessor` 只包含 bean 销毁回调之前的动作，没有之后。
