模板模式
模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。这里的“算法”,我们可以理解为广义上的“业务逻辑”,并不特指数据结构和算法中的“算法”。这里的算法骨架就是“模板”,包含算法骨架的方法就是“模板方法”,这也是模板方法模式名字的由来。
模板模式有两大作用:复用和扩展。其中复用指的是,所有的子类可以复用父类中提供的模板方法的代码。扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。
除此之外,我们还讲到回调。它跟模板模式具有相同的作用:代码复用和扩展。在一些框架、类库、组件等的设计中经常会用到,比如 JdbcTemplate 就是用了回调。相对于普通的函数调用,回调是一种双向调用关系。A 类事先注册某个函数 F 到 B 类,A 类在调用 B 类的 P 函数的时候,B 类反过来调用 A 类注册给它的 F 函数。这里的 F 函数就是“回调函数”。A 调用 B,B 反过来又调用 A,这种调用机制就叫作“回调”。
回调可以细分为同步回调和异步回调。从应用场景上来看,同步回调看起来更像模板模式,异步回调看起来更像观察者模式。回调跟模板模式的区别,更多的是在代码实现上,而非应用场景上。回调基于组合关系来实现,模板模式基于继承关系来实现。回调比模板模式更加灵活。
Spring中的模板方法
-
DefaultListableBeanFactory 中的 BeanFactoryPostProcessor 。
-
DefaultListableBeanFactory 中的 BeanPostProcessor 。
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的后置处理。
@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;
}
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;
}
}
参考代码
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);
}
}
参考
-
74 | 总结回顾23种经典设计模式的原理、背后的思想、应用场景等
原文始发于微信公众号(雨林寻北):Spring中的设计模式之模板模式
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/239341.html