以下将按高频使用频次与业务影响力排序,逐层拆解Spring中最具代表性的设计模式实现细节。
模板方法模式(Template Method)
模板方法模式定义了一个算法的骨架,而将一些步骤延迟到子类中实现。Spring中最具代表性的实现是AbstractApplicationContext的refresh()方法——这是整个Spring容器启动流程的核心骨架。
? 源码定位
类路径:org.springframework.context.support.AbstractApplicationContext#refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备上下文
prepareRefresh();
// 2. 初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 预处理BeanFactory
prepareBeanFactory(beanFactory);
try {
// 4. 子类可扩展点:注册BeanPostProcessors等
postProcessBeanFactory(beanFactory);
// 5. 调用BeanFactory后处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册Bean后处理器
registerBeanPostProcessors(beanFactory);
// ... 后续初始化逻辑
} catch (RuntimeException ex) {
// 异常处理与回滚
destroyBeans();
cancelRefresh(ex);
throw ex;
}
}
}
上述代码中,prepareRefresh()、obtainFreshBeanFactory()等为固定步骤;而postProcessBeanFactory()则是一个“钩子”方法,默认为空实现,允许子类(如AnnotationConfigWebApplicationContext)进行自定义扩展。这种设计既保证了启动流程的稳定性,又保留了灵活的可扩展性。
工厂模式(Factory Pattern)
Spring大量使用工厂模式解耦对象创建逻辑。其中BeanFactory是核心接口,其子类DefaultListableBeanFactory实现了复杂bean定义解析、依赖注入与循环依赖处理。
⚠️ 注意:Singleton vs Prototype
当scope="singleton"时,BeanFactory采用预初始化+缓存池策略;当scope="prototype"时,则每次调用getBean()均创建新实例。这一差异直接影响内存占用与并发性能——在高并发场景下,过度使用prototype可能导致GC压力激增。
更高级的工厂实现是FactoryBean接口。它允许开发者自定义复杂对象的创建逻辑,例如MyBatis中的SqlSessionFactoryBean:
public class SqlSessionFactoryBean implements FactoryBean {
private DataSource dataSource;
private String configLocation;
@Override
public SqlSessionFactory getObject() throws Exception {
return SqlSessionFactoryBuilder.build(
Resources.getResourceAsStream(configLocation),
new Environment.Builder("dev")
.dataSource(dataSource)
.build()
);
}
@Override
public Class> getObjectType() {
return SqlSessionFactory.class;
}
}
在Spring中注入@Autowired SqlSessionFactory sqlSessionFactory时,实际获取的是getObject()的返回值,而非FactoryBean实例本身。这种机制将复杂初始化逻辑封装在工厂内部,对外暴露简洁接口。
代理模式(Proxy Pattern)
Spring AOP的核心实现基于代理模式。根据目标类是否实现接口,Spring自动选择:
• JDK动态代理(接口实现) → 通过java.lang.reflect.Proxy生成代理
• CGLIB代理(无接口) → 通过继承目标类生成子类代理
? 如何强制使用CGLIB?
在配置类上添加:
@EnableAspectJAutoProxy(proxyTargetClass = true)
或在XML中:
<aop:aspectj-autoproxy proxy-target-class="true"/>
代理模式在事务管理中体现尤为明显。当调用@Transactional标注的方法时,Spring会通过代理拦截调用,在方法执行前后自动开启/提交/回滚事务——这一过程对业务代码完全透明。
策略模式(Strategy Pattern)
Spring事务传播行为(Propagation)是策略模式的典型应用。每种传播行为对应一个策略实现类:
TransactionTemplate.PROPAGATION_REQUIRED → 若存在事务则加入,否则新建
TransactionTemplate.PROPAGATION_REQUIRES_NEW → 总是新建事务,挂起当前事务
TransactionTemplate.PROPAGATION_NESTED → 若存在事务则在嵌套事务内执行
策略选择逻辑封装在AbstractPlatformTransactionManager中,其getTransaction()方法根据传播行为决定如何处理现有事务上下文。
// 简化版事务策略选择逻辑
protected TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException {
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
// 挂起当前事务,新建事务
return suspend(transaction);
}
// ... 其他策略
}
观察者模式(Observer Pattern)
Spring事件机制基于ApplicationEvent与ApplicationListener。核心组件SimpleApplicationEventMulticaster负责事件发布与监听器调用。
1事件发布
通过ApplicationEventPublisher.publishEvent()触发事件
2监听器注册
实现ApplicationListener或使用@EventListener注解
3异步事件
配置SimpleApplicationEventMulticaster.setTaskExecutor()实现异步通知
典型应用:用户注册成功后发布UserRegisteredEvent,由监听器触发发送欢迎邮件、积分奖励等后续操作,实现业务解耦。
单例模式(Singleton Pattern)
Spring容器中的Bean默认是单例的,但这与传统单例模式有本质区别:
- 非饿汉式:Bean在首次请求时创建(懒加载),而非容器启动时
- 非全局唯一:每个
ApplicationContext独立维护单例池
- 线程安全:通过
DefaultSingletonBeanRegistry.singletonObjects(ConcurrentHashMap)保证并发安全
? 单例陷阱:状态持有
单例Bean不应持有实例变量(非线程安全)!若需状态管理,应使用@Scope("prototype")或ThreadLocal封装。例如:避免在Controller中定义成员变量存储请求参数。
责任链模式(Chain of Responsibility)
Spring MVC中HandlerInterceptor链、Filter链均基于责任链模式实现。请求进入DispatcherServlet前,依次经过拦截器链处理。
// 拦截器执行流程简化示意
for (HandlerInterceptor interceptor : interceptors) {
if (!interceptor.preHandle(request, response, handler)) {
return; // 中断请求
}
}
// ... 执行Controller
// 返回时反向调用afterCompletion
这种设计使权限校验、日志记录、性能监控等横切逻辑与业务代码完全分离。