02-Spring中的设计模式之模板模式

模板模式

模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。这里的“算法”,我们可以理解为广义上的“业务逻辑”,并不特指数据结构和算法中的“算法”。这里的算法骨架就是“模板”,包含算法骨架的方法就是“模板方法”,这也是模板方法模式名字的由来。

模板模式有两大作用:复用和扩展。其中复用指的是,所有的子类可以复用父类中提供的模板方法的代码。扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。

除此之外,我们还讲到回调。它跟模板模式具有相同的作用:代码复用和扩展。在一些框架、类库、组件等的设计中经常会用到,比如 JdbcTemplate 就是用了回调。相对于普通的函数调用,回调是一种双向调用关系。A 类事先注册某个函数 F 到 B 类,A 类在调用 B 类的 P 函数的时候,B 类反过来调用 A 类注册给它的 F 函数。这里的 F 函数就是“回调函数”。A 调用 B,B 反过来又调用 A,这种调用机制就叫作“回调”。

回调可以细分为同步回调和异步回调。从应用场景上来看,同步回调看起来更像模板模式,异步回调看起来更像观察者模式。回调跟模板模式的区别,更多的是在代码实现上,而非应用场景上。回调基于组合关系来实现,模板模式基于继承关系来实现。回调比模板模式更加灵活。

Spring中的模板方法

  • DefaultListableBeanFactory 中的 BeanFactoryPostProcessor 。
  • DefaultListableBeanFactory 中的 BeanPostProcessor 。
1
2
3
4
5
org.springframework.context.annotation.internalConfigurationAnnotationProcessor // 注解配置处理
org.springframework.context.annotation.internalAutowiredAnnotationProcessor // 自动注入处理
org.springframework.context.annotation.internalCommonAnnotationProcessor // 通用注解处理
org.springframework.context.event.internalEventListenerProcessor // 事件处理类
org.springframework.context.event.internalEventListenerFactory // 事件监听类
  • 同一调用postProcessBeanFactory接口方法执行对BeanFactory的后置处理。
  • 同一调用 postProcessBeforeInitialization postProcessAfterInitialization 接口方法执行对Bean的后置处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;

/**
* Factory hook that allows for custom modification of new bean instances —
* for example, checking for marker interfaces or wrapping beans with proxies.
*/
public interface BeanPostProcessor {

@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

}

参考代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package engineer.spring.design;

import java.util.ArrayList;
import java.util.List;

/**
* 模板方法设计模式
*
* @author Q
*/
public class TemplateMethodTest {
public static void main(String[] args) {

MyBeanFactory beanFactory = new MyBeanFactory();
beanFactory.addBeanPostProcessor((bean) -> System.out.println("注入 @Autowired" + bean));
beanFactory.addBeanPostProcessor((bean) -> System.out.println("注入 @Resource" + bean));
beanFactory.addBeanPostProcessor((bean) -> System.out.println("注入 @Configuration" + bean));

System.out.println(beanFactory.getBean());

}

static class MyBeanFactory {
public Object getBean() {
Object bean = new Object();
System.out.println("构造 " + bean);
// 1. 解析@Autowired
// 2. 解析@Resource
System.out.println("依赖注入 " + bean);
postProcessorList.forEach(beanPostProcessor -> {
beanPostProcessor.inject(bean);
});
System.out.println("初始化 " + bean);
// 扩展功能需要修改代码
return bean;
}

public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
postProcessorList.add(beanPostProcessor);
}

private List<BeanPostProcessor> postProcessorList = new ArrayList<>();

}

static interface BeanPostProcessor {
// 依赖注入模板方法,通过调用接口,具体得实现将某些步骤推迟到子类中实现
void inject(Object bean);
}

}

参考