## Spring 对象的生命周期
对象的生命周期是指一个对象创建、存活、消亡的一个完整的过程,通过 IOC,Spring 接管了对象的控制权,所以也需要负责管理对象的生命周期,Spring 管理的对象生命周期分为三个阶段:创建阶段、初始化阶段、销毁阶段
### 创建阶段
* 如果配置文件中 `` 标签的 `scope` 属性值为 `"singleton"`,则 Spring 工厂创建时,就会创建该类的对象,且在项目运行的整个过程中,只会创建一次,用户每次调用工厂的 `getBean()` 方法获得的对象都是同一个
* 注意,如果`` 标签还设置了 `lazy-init` 属性值为 `"true"`,表明该类使用懒加载方式,也就是当用户第一次调用 `getBean()` 方法时才会创建对象,且只会创建一次
* 如果配置文件中 `` 标签的 `scope` 属性值为 `"prototype"`,则 Spring 工厂会在用户调用 `getBean()` 方法方法时才会创建对象,且每次获得对象都是不同的
### 初始化阶段
Spring 工厂在创建完对象后,会调用初始化方法,完成对象的初始化操作,注意,该初始化方法需要程序员根据需求编码实现,但是由 Spring 工厂进行调用,主要有以下两种方式定义初始化方法
* 类实现 `InitializingBean` 接口,并实现其中的 `afterPropertiesSet()` 方法,在该方法中完成对象的初始化,无需修改配置文件
* 类中编写一个普通方法,例如 `public void myInit(){}`,然后在配置文件中对应的 `` 标签添加 `init-method` 属性,值为初始化方法的方法名,表明该方法是初始化方法
**注意**
1. 如果一个类,同时用以上两种方法进行初始化,则实际的初始化方法执行顺序是,先执行 `InitializingBean` 的初始化的方法,再执行普通初始化方法
2. 注入操作会发生在初始化之前,所以 `InitializingBean` 接口中的初始化方法命名为 `afterPropertiesSet()`
### 销毁阶段
Spring 销毁对象之前,会调用对象的销毁方法,完成销毁操作,有以下两种方式定义销毁方法
* 类实现 `DisposableBean` 接口,并实现其中的 `destroy()` 方法,在该方法中完成对象销毁前需要进行的操作,无需修改配置文件
* 类中编写一个普通方法,例如 `public void myDestroy(){}`,然后在配置文件中对应的 `` 标签添加 `destroy-method` 属性,值为销毁方法的方法名,表明该方法是销毁方法
**注意**
1. Spring 在工厂关闭时才会进行销毁对象的操作,即调用 `ApplicationContext` 对象的 `close()` 方法时
2. 如果一个类,同时用以上两种方法完成对象的销毁,则实际销毁方法的执行顺序是,先执行 `DisposableBean` 接口的销毁方法,再执行普通销毁方法
3. 销毁方法只适用于只创建一次的对象,即 `scope="singleton"`,`Connection` 或 `SqlSession` 等对象应该自行销毁或归还到连接池
## Spring Bean 的后处理
Spring 通过 `BeanPostProcessor` 接口对工厂创建的(每一个)对象进行再加工
### Spring Bean 后处理原理
`BeanPostProcessor` 接口规定有两个需要实现的方法,Spring 会调用这两个方法完成对象的后处理
1. `Object postProcessBeforeInitialization(Object bean,String beanName)`
该方法会在 Spring 创建对象、完成注入后,初始化操作前,通过参数获取对象,然后进行加工,最后再返回交给 Spring
2. `Object postProcessAfterInitialization(Object bean,Sring beanName)`
该方法会在 Spring 完成对对象的初始化操作后,通过参数获取对象,然后进行加工,最后再返回交给 Spring
在实际运用中,很少对对象进行初始化操作,所以后处理过程也不必分初始化前后,只需实现 `postProcessAfterInitialization()` 方法即可
### 实例
创建一个用于测试的类
```java
public class Product {
private int id;
private String name;
/*
... ...
set get toStirng 方法
*/
}
```
创建一个类实现 `BeanPostProcessor` 接口,实现 `postProcessAfterInitialization()` 方法,判断如果传入对象是 `Product` 对象,则进行处理
```java
package cool.yzt.postprocessor;
import cool.yzt.domain.Product;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Product) {
Product p = (Product)bean;
p.setName("电脑");
System.out.println(beanName);
}
return bean;
}
}
```
配置文件,注入 `product` 的属性
```java
```
测试
```java
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Product p1 = ctx.getBean("product",Product.class);
Product p2 = ctx.getBean("product",Product.class);
System.out.println(p1);
System.out.println(p2);
System.out.println(p1==p2);
```
结果
```
product
product
Product{id=10001, name='电脑'}
Product{id=10001, name='电脑'}
false
```
可以看到,Spring 确实对创建的对象进行了后处理,且该操作发生在在注入之后
## 总结 Spring 工厂创建对象的流转过程

## 参考
[孙哥说Spring5](https://www.bilibili.com/video/BV185411477k)

Spring | 对象的生命周期