学完这篇,你能在 Spring 源码里准确指出 9 种设计模式的落地位置,并且知道每一种在什么场景下该照着抄、什么场景下别硬套。
第一步:准备读源码的环境
不用完整拉 Spring 源码,直接在 IDEA 里用 Maven 依赖 + 反编译就够了:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.39</version>
</dependency>
在 IDEA 中按 Ctrl+N(Mac 是 Cmd+O)输入类名即可跳转,Ctrl+Alt+B 看接口实现类列表——后文每个模式都靠这两个快捷键定位。
注意:看 AOP 相关类时确认引入的是 spring-aop 和 spring-context,只有 spring-core 是看不到 JdkDynamicAopProxy 的。
第二步:工厂模式 —— BeanFactory 与 FactoryBean
org.springframework.beans.factory.BeanFactory 是最大的工厂接口,getBean() 就是工厂方法。真正体现"工厂"设计的是 FactoryBean:你实现 getObject(),Spring 容器里存的不是你本身,而是它的返回值。
典型应用:MyBatis 的 SqlSessionFactoryBean、MapperFactoryBean。
第三步:单例模式 —— 默认 scope
Spring 容器中 Bean 默认 scope="singleton",但不是饿汉也不是经典双重检查锁,而是注册表式单例:DefaultSingletonBeanRegistry 里的三级缓存 singletonObjects。
@Bean
public UserService userService() { return new UserService(); } // 默认单例
注意:单例 Bean 注入 prototype Bean 时,只会注入一次,之后拿到的永远是同一个。要每次拿新的,用 @Lookup 或注入 ObjectProvider<T>。
第四步:代理模式 —— AOP 的底层
入口类:JdkDynamicAopProxy(基于接口,实现 InvocationHandler)和 CglibAopProxy(继承目标类生成子类)。切哪个由 AopProxyFactory 决定。
验证方式:给一个 Service 加上 @Transactional,启动后打印 service.getClass().getName(),带接口的会看到 com.sun.proxy.$Proxy,不带接口的是 xxx$$EnhancerBySpringCGLIB。
注意:JDK 代理要求目标类必须有接口,否则报 BeanNotOfRequiredTypeException;Spring Boot 2.x 起默认 proxyTargetClass=true,强制 CGLIB。
第五步:模板方法 —— JdbcTemplate 与 refresh()
父类定骨架,子类填细节。两处最典型:
JdbcTemplate.execute() 把"拿连接→建 Statement→执行→释放"写死,把 SQL 加工交给 StatementCallback 回调;
AbstractApplicationContext.refresh() 定义 12 步启动流程,postProcessBeanFactory()、onRefresh() 留作空实现给子类覆盖。
第六步:观察者模式 —— 事件机制
ApplicationEventPublisher.publishEvent() 发布,ApplicationListener<T> 或 @EventListener 订阅,SimpleApplicationEventMulticaster 负责广播。
@Component
public class OrderListener {
@EventListener
public void on(OrderCreatedEvent e) { /* ... */ }
}
注意:@EventListener 默认是同步执行,发事件会阻塞主流程。要异步必须加 @Async 并在配置类上开 @EnableAsync。
第七步:适配器模式 —— HandlerAdapter
Spring MVC 的 DispatcherServlet 只认 HandlerAdapter 接口,RequestMappingHandlerAdapter、HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter 各自把不同类型的 Handler 适配成统一调用形式。另一个是 AdvisorAdapter,把不同 Advice 适配成 MethodInterceptor。
第八步:装饰器模式 —— ContentCachingRequestWrapper
HttpServletRequestWrapper、ContentCachingRequestWrapper 都通过继承 + 组合,在原有对象上叠加能力而不改原类。Spring 的 TransactionAwareCacheDecorator 也是给 Cache 加事务同步。
和代理的区别:代理控制"能不能进",装饰器负责"进去前后多干点事"。
第九步:策略模式与责任链模式
策略:Resource 接口(ClassPathResource/FileSystemResource/UrlResource)、InstantiationStrategy(SimpleInstantiationStrategy vs CglibSubclassingInstantiationStrategy)、PlatformTransactionManager 的三套实现。容器按条件挑一个实现注入。
责任链:HandlerExecutionChain 串起 HandlerInterceptor(preHandle→postHandle→afterCompletion),FilterChainProxy 串起 Spring Security 的过滤器链。手写时让每个节点持有 next 引用即可。
小结
- 9 种模式在 Spring 里的对应类:BeanFactory/FactoryBean、DefaultSingletonBeanRegistry、JdkDynamicAopProxy、JdbcTemplate、ApplicationEventPublisher、HandlerAdapter、ContentCachingRequestWrapper、Resource、HandlerExecutionChain。
- 读源码靠
Ctrl+N 找类、Ctrl+Alt+B 找实现,比背 UML 有用得多。
- 三个高频坑:单例注入 prototype 失效、
@EventListener 默认同步、JDK 代理必须有接口。
- 抄之前先问一句:我的场景真的需要这层抽象吗?过度设计比不设计更贵。