原文来自于:zha-ge.cn/java/117
面试官最爱刁难:Spring 框架里到底用了多少经典设计模式?
每次面试聊到 Spring,几乎必考的一个灵魂拷问就是------
"Spring 框架用了哪些设计模式?举几个例子。"
这题表面看着像背书,其实是面试官在判断:你到底只是"用过 Spring",还是"理解了 Spring 背后的设计哲学"。
我第一次被问的时候,脑子一片空白:"单例?工厂?还有......有吗?" 面试官微微一笑:"还有十多个呢,你才说俩?"
于是我带着不甘和羞耻翻源码、啃文档,才发现:Spring 不仅是一个 IOC 框架,更是设计模式的博物馆。
1. 工厂模式(Factory Pattern):Bean 是"造"出来的
应用场景: BeanFactory
、ApplicationContext
Spring 的核心容器就是一个大工厂,它接管了 Bean 的创建过程。你写:
java
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = context.getBean("userService", UserService.class);
你看不到 new
,Bean 却诞生了。这就是典型的工厂模式:把对象创建的细节封装起来,对外只暴露一个统一的获取接口。
- IOC 容器本质就是工厂
- 工厂负责 Bean 的创建、依赖注入、生命周期管理
- 让上层代码"面向接口编程",而不是"new 对象"
📌 面试小技巧:这题别只说"工厂模式",一定要提到 IOC 容器和 BeanFactory
。
2. 单例模式(Singleton Pattern):Bean 默认是唯一的
应用场景: Spring Bean 的默认作用域
我们都知道 Spring Bean 默认是单例:
java
@Component
public class UserService {}
容器里只有一份 UserService
实例,不管注入多少次,拿到的都是同一个。
这就是典型的单例模式,它避免了重复创建对象带来的资源浪费,也保证了全局状态的一致性。
⚠️ 小坑提醒:单例 ≠ 线程安全。Bean 是单例的没错,但如果你在里面写了可变状态变量,线程安全问题还是要自己管。
3. 代理模式(Proxy Pattern):AOP 的灵魂
应用场景: Spring AOP、事务管理、拦截器链
Spring 的 AOP 本质就是一套动态代理:
- JDK 动态代理:基于接口
- CGLIB 代理:基于子类
比如你写了:
java
@Transactional
public void saveUser() { ... }
Spring 会在运行时为这个 Bean 生成代理对象,方法调用前后织入事务逻辑。你以为你调的是原方法,其实你调的是代理。
这就是典型的代理模式:在不修改原始代码的情况下,增强对象的功能。
4. 模板方法模式(Template Method Pattern):JDBC Template / Redis Template
应用场景: JdbcTemplate
、RestTemplate
、RedisTemplate
Spring 里一堆 "Template" 结尾的类,背后都是模板方法模式:
- 父类封装公共流程(比如获取连接、异常处理、关闭资源)
- 子类或回调实现具体步骤(比如执行 SQL)
例子:
java
jdbcTemplate.query("SELECT * FROM user", rs -> {
while (rs.next()) {
// 处理结果
}
});
你不用管资源释放和异常处理,模板方法帮你包好了。这是 Spring 大量"帮你做脏活累活"的根源。
5. 观察者模式(Observer Pattern):事件驱动的秘密
应用场景: Spring 事件机制(ApplicationEventPublisher
)
Spring 的事件机制是标准的观察者模式:
- 事件源:
ApplicationEventPublisher
- 事件:继承
ApplicationEvent
- 监听器:实现
ApplicationListener
java
@Component
public class MyListener implements ApplicationListener<MyEvent> {
public void onApplicationEvent(MyEvent event) {
System.out.println("收到事件:" + event.getMsg());
}
}
这种松耦合的事件驱动思想广泛用于系统解耦、领域事件发布、状态监听等场景。
6. 适配器模式(Adapter Pattern):统一接口的"翻译官"
应用场景: HandlerAdapter
、WebMvcConfigurer
Spring MVC 中的 HandlerAdapter
就是一个适配器:
- 不同的 Controller(方法签名、返回类型都可能不同)
DispatcherServlet
无需关心具体实现- 由
HandlerAdapter
把它们"翻译"为统一的处理接口
这样,框架的上层调用逻辑不变,底层的控制器实现却可以千变万化。
7. 装饰器模式(Decorator Pattern):BeanPostProcessor、BeanWrapper
应用场景: Bean 初始化前后的增强
BeanPostProcessor
是 Spring 中经典的装饰器使用场景。它允许你在 Bean 创建完成前后,动态增强 Bean 的行为:
java
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// 包装或增强 bean
return bean;
}
AOP 其实也有装饰器的影子:你在原有 Bean 外面套了一层"外衣",增加了功能但不改原本的逻辑。
8. 策略模式(Strategy Pattern):注入不同实现类
应用场景: ApplicationContext.getBean()
、Converter
、Validator
Spring 容器天生支持策略模式:接口多实现的时候,你可以按名字、按条件注入不同策略。
java
@Autowired
private PaymentStrategy paymentStrategy;
只要定义多个实现类,Spring 会根据上下文或 @Qualifier
决定用哪个。
这也是为什么 Spring 项目里"扩展性"这么强的根本原因:接口 + 多策略实现。
9. 构建者模式(Builder Pattern):BeanDefinitionBuilder
应用场景: BeanDefinition 的定义与注册
Spring 的底层在创建 BeanDefinition 时就用到了构建者模式:
java
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(UserService.class);
builder.addPropertyValue("name", "Deck");
你一步步设置属性,最后由容器统一构建出完整 Bean 定义对象。
10. 职责链模式(Chain of Responsibility):拦截器链 / BeanFactoryPostProcessor
应用场景: Spring MVC 的拦截器链、Filter 链
Spring MVC 的 HandlerInterceptor
就是责任链模式的标准实现: 每个拦截器负责自己的一段逻辑,处理完再交给下一个。
同理,Bean 的初始化过程也会被一连串 BeanPostProcessor
"处理链"加工。
面试官杀手锏回答
面试被问到这题时,别傻傻只说"两三个"。推荐答法是这样的:
Spring 框架大量使用了经典设计模式,比如:
- 工厂模式 :IOC 容器管理 Bean 创建(
BeanFactory
、ApplicationContext
)- 单例模式:Bean 默认作用域是单例
- 代理模式:AOP、事务增强基于动态代理
- 模板方法模式 :
JdbcTemplate
等封装固定流程- 观察者模式:事件发布与监听
- 适配器模式 :
HandlerAdapter
解耦 Controller 调用- 装饰器模式 :
BeanPostProcessor
动态增强 Bean- 策略模式:多实现注入按需切换
- 职责链模式:拦截器链、Bean 后置处理链
然后加一句收尾:"Spring 就是设计模式的实战手册,学懂这些模式能让我们更好地理解它的源码和扩展点。"
写在最后
当年我以为"设计模式"只是面试背的八股文,Spring 用起来也不需要懂这些。 现在回头看,Spring 就像是一本活着的《设计模式 GOF》:每一种模式都不是纸上谈兵,而是有血有肉地活在框架里。
所以,下次再有人问你"Spring 用了哪些设计模式",别只说"单例和工厂"了。 真正的高手,早已把设计模式变成了写代码的肌肉记忆。