前言
前言首先介绍模版方法模式的原理以及其架构,主要为了服务于Spring源码的理解。模板方法模式Spring如何利用这个模式和扩展点比如BeanPostProcessor来实现生命周期管理,本文将在详细解析。
Spring的部分。Spring的生命周期管理涉及到Bean的创建、初始化、销毁等过程。BeanPostProcessor是Spring中的一个扩展点,可以在Bean初始化前后进行自定义处理。那模板方法模式在Spring中是如何应用的呢?可能是在Bean的生命周期过程中,Spring定义了一个模板方法,比如实例化Bean、填充属性、初始化等步骤,而这些步骤中的某些部分可以通过BeanPostProcessor这样的扩展点让开发者自定义。
AbstractApplicationContext的refresh方法可能是一个模板方法,里面定义了整个容器刷新的流程,而具体的某些步骤可能由子类或通过扩展点来实现。比如,在Bean的初始化阶段,Spring会调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法,这些就是扩展点,允许用户在Bean初始化前后插入自定义逻辑。
Spring在初始化Bean时,有一个模板方法定义了初始化流程:实例化Bean、注入依赖、调用BeanPostProcessor的前置处理、执行初始化方法(如InitializingBean的afterPropertiesSet)、调用BeanPostProcessor的后置处理。这个过程是模板方法,而BeanPostProcessor就是扩展点,允许开发者插入自己的逻辑。
模版方法模型在Spring框架中多次被使用。其中,AbstractBeanFactory中的doGetBean可能是一个模板方法,里面调用了createBean等步骤,而具体的创建过程可能由子类实现,如DefaultListableBeanFactory。或者,在初始化过程中,AbstractAutowireCapableBeanFactory的initializeBean方法可能是一个模板方法,其中调用了applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization,而这些方法又调用了所有BeanPostProcessor的处理方法。
Spring通过模板方法定义了Bean的生命周期流程,而通过BeanPostProcessor等扩展点,允许用户在特定步骤插入自定义处理。这种设计使得Spring的核心流程稳定,同时提供了高度的扩展性。
需要举出具体的类和方法,比如在AbstractApplicationContext的refresh方法中,调用了obtainFreshBeanFactory、prepareBeanFactory、postProcessBeanFactory等,其中postProcessBeanFactory可能是一个钩子方法,由子类实现,这就是模板方法模式的应用。同时,在Bean的初始化阶段,BeanPostProcessor的应用就是通过扩展点来增强功能。
总结来说,模板方法模式的概念是首要,以及Spring如何利用该模式结合扩展点(如BeanPostProcessor)来管理Bean的生命周期。需要明确模板方法模式的结构,以及在Spring源码中的具体应用,特别是生命周期管理中的各个步骤如何通过模板方法定义,并通过扩展点允许用户自定义。
模板方法模式与 Spring 生命周期管理详解
一、模板方法模式(Template Method Pattern)
核心思想:定义一个算法的骨架,将某些步骤延迟到子类实现,使得子类可以不改变算法结构即可重定义某些步骤。
类图结构:
plaintext
+---------------------+
| AbstractClass |
+---------------------+
| +templateMethod() | ← 定义算法流程
| +step1() | ← 具体或抽象方法
| +step2() {抽象方法} |
| +step3() {钩子方法} |
+---------------------+
^
|
+---------------------+
| ConcreteClass |
+---------------------+
| +step2() | ← 实现抽象方法
| +step3() | ← 覆盖钩子方法
+---------------------+
关键特点:
- 模板方法 :定义算法流程(如
templateMethod()
),通常是final
方法。 - 抽象步骤 :子类必须实现的步骤(如
step2()
)。 - 钩子方法 :子类可选覆盖的默认实现(如
step3()
)。
代码示例:
java
public abstract class AbstractProcessor {
// 模板方法(final 防止子类修改流程)
public final void process() {
step1();
step2(); // 抽象方法,子类实现
if (needStep3()) { // 钩子方法
step3();
}
}
private void step1() {
System.out.println("执行固定步骤1");
}
public abstract void step2();
protected boolean needStep3() { // 钩子方法默认实现
return true;
}
protected void step3() {
System.out.println("执行默认步骤3");
}
}
public class ConcreteProcessor extends AbstractProcessor {
@Override
public void step2() {
System.out.println("子类实现步骤2");
}
@Override
protected boolean needStep3() { // 覆盖钩子方法
return false;
}
}
二、Spring 如何结合模板方法模式与扩展点管理 Bean 生命周期
Spring 的生命周期管理通过 模板方法模式 定义核心流程,并借助 扩展点(如 BeanPostProcessor
) 允许开发者插入自定义逻辑。
1. Spring Bean 生命周期核心流程
Spring 容器管理 Bean 的核心流程如下(简化版):
- 实例化:通过反射或工厂方法创建 Bean 实例。
- 属性填充 :注入依赖(如
@Autowired
)。 - 初始化前处理 :调用
BeanPostProcessor.postProcessBeforeInitialization()
。 - 初始化 :执行
InitializingBean.afterPropertiesSet()
或自定义init-method
。 - 初始化后处理 :调用
BeanPostProcessor.postProcessAfterInitialization()
。 - 销毁前处理 :容器关闭时执行
DisposableBean.destroy()
或自定义destroy-method
。
2. 模板方法模式在 Spring 中的应用
核心类 :AbstractAutowireCapableBeanFactory
关键方法 :initializeBean()
定义了 Bean 初始化的模板流程。
源码解析(Spring 5.x):
java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// --- 初始化前处理 ---
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
// --- 执行初始化方法 ---
try {
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException(...);
}
// --- 初始化后处理 ---
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
流程说明:
- 模板方法 :
initializeBean()
定义了初始化流程的骨架。 - 扩展点 :通过
BeanPostProcessor
的Before
和After
方法插入自定义逻辑。 - 钩子方法 :
invokeInitMethods()
调用InitializingBean
接口的afterPropertiesSet()
,用户可选择实现该接口。
3. 扩展点 BeanPostProcessor
的作用
BeanPostProcessor
是 Spring 的核心扩展点,允许在 Bean 初始化前后插入逻辑。例如:
- 自定义注解处理 :如
@PostConstruct
注解的解析。 - 代理增强 :AOP 动态代理的创建(如
AbstractAutoProxyCreator
)。
示例 :自定义 BeanPostProcessor
java
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof UserService) {
System.out.println("初始化前处理: " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof UserService) {
System.out.println("初始化后处理: " + beanName);
}
return bean;
}
}
4. Spring 容器启动流程中的模板方法
核心类 :AbstractApplicationContext
关键方法 :refresh()
定义了容器启动的完整流程。
源码流程:
java
public void refresh() {
// 1. 准备刷新上下文
prepareRefresh();
// 2. 获取 BeanFactory 并加载 Bean 定义
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 配置 BeanFactory(如添加 BeanPostProcessor)
prepareBeanFactory(beanFactory);
try {
// 4. 后处理 BeanFactory(钩子方法)
postProcessBeanFactory(beanFactory);
// 5. 调用 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源、事件广播器等
initMessageSource();
initApplicationEventMulticaster();
// 8. 子类扩展点:初始化其他特殊 Bean
onRefresh();
// 9. 注册事件监听器
registerListeners();
// 10. 完成 BeanFactory 初始化(实例化所有非懒加载单例 Bean)
finishBeanFactoryInitialization(beanFactory);
// 11. 完成刷新流程(发布事件等)
finishRefresh();
} catch (BeansException ex) {
// 异常处理...
}
}
模板方法设计:
- 固定步骤 :如
prepareRefresh()
,obtainFreshBeanFactory()
是固定流程。 - 钩子方法 :
postProcessBeanFactory()
,onRefresh()
允许子类扩展。 - 扩展点 :
BeanFactoryPostProcessor
,BeanPostProcessor
允许用户插入自定义逻辑。
三、总结
-
模板方法模式在 Spring 中的应用
- 定义核心流程(如 Bean 初始化、容器刷新)。
- 通过抽象方法(如
postProcessBeanFactory()
)和钩子方法(如onRefresh()
)支持扩展。
-
扩展点与生命周期管理
BeanPostProcessor
在 Bean 初始化前后插入逻辑(如 AOP 代理、注解解析)。BeanFactoryPostProcessor
在 Bean 定义加载后、实例化前修改元数据(如占位符替换)。
实际应用场景:
- AOP 代理 :
AbstractAutoProxyCreator
通过BeanPostProcessor
在初始化后生成代理对象。 - 事务管理 :
InfrastructureAdvisorAutoProxyCreator
结合@Transactional
生成事务代理。 - 自定义初始化 :实现
InitializingBean
或使用@PostConstruct
注解。
优势:
- 稳定性:核心流程固定,避免逻辑分散。
- 扩展性:通过扩展点灵活增强功能,符合开闭原则。
示例代码片段(Spring 内部源码简化):
java
// AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(...) {
applyBeanPostProcessorsBeforeInitialization(bean, beanName); // 扩展点
invokeInitMethods(...); // 模板方法中的步骤
applyBeanPostProcessorsAfterInitialization(bean, beanName); // 扩展点
return bean;
}
通过模板方法模式与扩展点的结合,Spring 实现了高度可定制且稳定的生命周期管理机制。