title: Spring 框架源码解读3
date: 2020/04/16 09:25
本节内容 & 思考题
Spring 中的 bean 的生命周期?
image- 通过xml配置文件或者注解扫描获取要实例化bean的信息,并使用反射创建实例
- 如果有需要注入的属性,则进行注入
- 执行一些 *Aware 接口的方法
- 调用实现了 BeanPostProcessor 接口的前置处理方法
- 执行实现 InitializingBean bean的 afterPropertiesSet() 方法
- 调用定义的 init-method 方法
- 调用实现了 BeanPostProcessor 接口的后置处理方法
- 要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
- 调用定义的 destory-method 方法
本节内容就会带大家实现 5 6 8 9
适配器模式:将普通对象适配成 InitializingBean
实现初始化 bean 的方法
1、在 BD 中新增字段
private String initMethod;
2、修改 AbstractBeanFactory#createBean() 方法
/**
* 根据 bd 创建对象
* <p>
* 1)创建bean 日后需要对有参构造进行扩展
* 2)注入属性 日后新增
* 3)执行初始化操作
* 4)注册销毁的处理
*/
private Object createBean(BeanDefinition beanDefinition) {
// 1、创建 bean
Object bean = ReflectUtil.newInstance(beanDefinition.getClassName());
// 2、注入属性 todo
// 3、执行初始化操作(在 Spring 中是直接调用的该类中的 initializeBean 方法,为了让他面向对象一点,我给他抽出一个类)
InitializeBeanAdapter initializeBeanAdapter = new InitializeBeanAdapter(bean, beanDefinition);
initializeBeanAdapter.afterPropertiesSet();
// 4、注册销毁的处理 todo
return bean;
}
3、InitializeBean 接口 & InitializeBeanAdapter 适配器
public interface InitializingBean {
/**
* 设置所有提供的bean属性后,由BeanFactory调用。
*/
void afterPropertiesSet();
}
public class InitializeBeanAdapter implements InitializingBean {
private Object bean;
private BeanDefinition bd;
public InitializeBeanAdapter(Object bean, BeanDefinition bd) {
this.bean = bean;
this.bd = bd;
}
/**
* 设置所有提供的bean属性后,由BeanFactory调用。
*/
@Override
public void afterPropertiesSet() {
// 1、处理 @PostConstruct 注解,执行注解的方法(此处 Spring 是采用后置处理器实现的,为什么要采用这个实现,而不是直接调用呢?)
this.postConstruct();
// 2、如果该 bean 实现了 InitializingBean 接口,则调用
this.initializingBean();
// 3、处理用户在 xml 文件中配置的 init-method 方法
this.customInit();
}
private void customInit() {
String initMethod = bd.getInitMethod();
if (ObjectUtil.isNotNull(initMethod)) {
ReflectUtil.invoke(bean, initMethod);
}
}
private void initializingBean() {
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
}
private void postConstruct() {
for (Method method : ReflectUtils.getMethodsByAnnotation(bean.getClass(), PostConstruct.class)) {
ReflectUtil.invoke(bean, method);
}
}
}
4、测试
public class TestJsonBF {
public static void main(String[] args) {
ListableBeanFactory bf = new JsonBeanFactoryImpl("/Users/x5456/IdeaProjects/Summer/src/test/resources/apple.json");
Apple apple = bf.getBean("apple", Apple.class);
}
}
apple.json
[
{
"name": "apple",
"className": "cn.x5456.summer.Apple",
"initMethod": "init"
}
]
public class Apple implements InitializingBean {
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean");
}
public void init() {
System.out.println("init-method");
}
@PostConstruct
public void func() {
System.out.println("@PostConstruct");
}
@PostConstruct
public void func2() {
System.out.println("@PostConstruct2");
}
}
集成销毁方法
1、修改 BD
private String destroyMethod;
2、修改 AbstractBeanFactory#createBean() 方法
/**
* 根据 bd 创建对象
* <p>
* 1)创建bean 日后需要对有参构造进行扩展
* 2)注入属性 日后新增
* 3)执行初始化操作
* 4)注册销毁的处理
*/
private Object createBean(BeanDefinition beanDefinition) {
// 1、创建 bean
Object bean = ReflectUtil.newInstance(beanDefinition.getClassName());
// 2、注入属性 todo
// 3、执行初始化操作(在 Spring 中是直接调用的该类中的 initializeBean 方法,为了让他面向对象一点,我给他抽出一个类)
InitializeBeanAdapter initializeBeanAdapter = new InitializeBeanAdapter(bean, beanDefinition);
initializeBeanAdapter.afterPropertiesSet();
// 4、注册销毁的处理
if (this.check(beanDefinition, bean)) {
registry.registerDisposableBean(beanDefinition.getName(), new DisposableBeanAdapter(bean, beanDefinition));
}
return bean;
}
/**
* 检查是否具有销毁方法
*/
private boolean check(BeanDefinition bd, Object bean) {
return ObjectUtil.isNotNull(bd.getDestroyMethod()) ||
bean instanceof DisposableBean ||
CollectionUtil.isNotEmpty(ReflectUtils.getMethodsByAnnotation(bean.getClass(), PreDestroy.class));
}
3、DisposableBean & DisposableBeanAdapter
public interface DisposableBean {
/**
* 由BeanFactory在销毁bean时调用。
*/
void destroy();
}
public class DisposableBeanAdapter implements DisposableBean {
private Object bean;
private BeanDefinition bd;
public DisposableBeanAdapter(Object bean, BeanDefinition bd) {
this.bean = bean;
this.bd = bd;
}
/**
* 由BeanFactory在销毁bean时调用。
*/
@Override
public void destroy() {
// 1、处理 @PreDestroy 注解,执行注解的方法(此处 Spring 是采用后置处理器实现的,为什么要采用这个实现,而不是直接调用呢?)
this.postPreDestroy();
// 2、如果该 bean 实现了 DisposableBean 接口,则调用
this.disposableBean();
// 3、处理用户在 xml 文件中配置的 destroy-method 方法
this.customDestroy();
}
private void customDestroy() {
String destroyMethod = bd.getDestroyMethod();
if (ObjectUtil.isNotNull(destroyMethod)) {
ReflectUtil.invoke(bean, destroyMethod);
}
}
private void disposableBean() {
if (bean instanceof DisposableBean) {
((DisposableBean) bean).destroy();
}
}
private void postPreDestroy() {
for (Method method : ReflectUtils.getMethodsByAnnotation(bean.getClass(), PreDestroy.class)) {
ReflectUtil.invoke(bean, method);
}
}
}
4、销毁信息注册中心
public class DefaultSingletonBeanRegistry {
private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();
/** 注册销毁信息 */
public void registerDisposableBean(String beanName, DisposableBean bean) {
this.disposableBeans.put(beanName, bean);
}
/** 执行销毁方法 */
public void destroySingletons() {
// 调用销毁方法
for (DisposableBean disposableBean : disposableBeans.values()) {
disposableBean.destroy();
}
// 清空 map
disposableBeans.clear();
}
}
5、在 BF 中新增调用单例对象销毁方法
/**
* 执行单例对象销毁方法
* <p>
* 那么原型的怎么办?
* <p>
* 原型对象在获取的时候会执行初始化操作,且不会执行销毁操作
* <p>
* Note: 在 Spring5.0 中,这个方法在 ConfigurableBeanFactory 中扩展,但是如果新增这个接口
* 会将类之间的逻辑变得十分复杂,有悖于我们做这个教程的初衷,所以采用 default 方法的方式,让 ABF
* 实现这个接口,而不用 AAP 实现这个接口
*/
default void destroySingletons() {
}
ABF 实现
@Override
public void destroySingletons() {
registry.destroySingletons();
}
6、测试
public class TestJsonBF {
public static void main(String[] args) {
ListableBeanFactory bf = new JsonBeanFactoryImpl("/Users/x5456/IdeaProjects/Summer/src/test/resources/apple.json");
Apple apple = bf.getBean("apple", Apple.class);
bf.destroySingletons();
}
}
apple.json
[
{
"name": "apple",
"className": "cn.x5456.summer.Apple",
"initMethod": "init",
"destroyMethod": "destroyMethod"
}
]
public class Apple implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean");
}
public void init() {
System.out.println("init-method");
}
@PostConstruct
public void func() {
System.out.println("@PostConstruct");
}
@PostConstruct
public void func2() {
System.out.println("@PostConstruct2");
}
// ---> 销毁
@Override
public void destroy() {
System.out.println("DisposableBean");
}
public void destroyMethod() {
System.out.println("destroyMethod");
}
@PreDestroy
public void func3() {
System.out.println("@PreDestroy");
}
}
ApplicationContext 新增对对象的销毁方法
1、ApplicationContext 新增 close 方法
AP
/**
* 关闭容器
*/
void close();
AAP 实现
public abstract class AbstractApplicationContext implements ApplicationContext {
// ...
// 关闭钩子,防止意外关闭
private Thread shutdownHook = new Thread(AbstractApplicationContext.this::doClose);
/**
* 加载或刷新配置文件(例如 XML、JSON)
* <p>
* 模版方法模式
*/
@Override
public void refresh() {
// ...
// 注册关闭钩子
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
/**
* 关闭容器
*/
@Override
public void close() {
// 执行关闭操作
this.doClose();
// 移除关闭钩子
if (ObjectUtil.isNotNull(shutdownHook)) {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
}
private void doClose() {
// 销毁单例的 bean
this.getBeanFactory().destroySingletons();
}
2、测试
public class TestJsonAP {
public static void main(String[] args) {
FileSystemJsonApplicationContext fileSystemJsonApplicationContext = new FileSystemJsonApplicationContext(new String[]{
"/Users/x5456/IdeaProjects/Summer/src/test/resources/apple.json"
});
fileSystemJsonApplicationContext.close();
}
}
Spring 0.9
0.9 中并没有提供 DisposableBean 等销毁方法,所以本节是参考 5.0 完成。
Spring 5.0
1、初始化操作
image创建bean之后会调用他们的后置处理器
image然后通过反射调用使用 @PostConstruct 注释的方法
之后调用 invokeInitMethods 方法:
image所以,顺序是 @PostConstruct InitializingBean init-method
2、注册销毁
在初始化完成后,Spring 会注册销毁方法。
image image它采用了一个注册中心存放 DisposableBeanAdapter
imageDisposableBeanAdapter#destroy()
image3、调用销毁
image最终会调用到这里,调用 DisposableBeanAdapter#destroy()
image
网友评论