文章目录
- [1 Spring中设计模式](#1 Spring中设计模式)
-
- [1.1 概述](#1.1 概述)
- [1.2 深度解析](#1.2 深度解析)
-
- [1.2.1 工厂模式(Spring 心脏)](#1.2.1 工厂模式(Spring 心脏))
- [1.2.2 单例模式(Spring Bean 默认作用域)](#1.2.2 单例模式(Spring Bean 默认作用域))
- [1.2.3 代理模式(AOP 灵魂)](#1.2.3 代理模式(AOP 灵魂))
- [1.2.4 模板方法模式(JdbcTemplate 一族)](#1.2.4 模板方法模式(JdbcTemplate 一族))
- [1.2.5 观察者模式(事件机制)](#1.2.5 观察者模式(事件机制))
- [1.2.6 适配器模式(Spring MVC 的核心)](#1.2.6 适配器模式(Spring MVC 的核心))
- [1.2.7 策略模式](#1.2.7 策略模式)
1 Spring中设计模式
1.1 概述
Spring 框架中用到的设计模式非常多,面试中最常被考察的有 9 大设计模式:
| 设计模式 | Spring 中的典型应用 | 一句话说明 |
|---|---|---|
| 工厂模式 | BeanFactory、ApplicationContext |
把对象的创建过程封装起来 |
| 单例模式 | Bean 的默认作用域 |
整个容器中只有一个实例 |
| 代理模式 | AOP(JDK 动态代理 / CGLIB) | 不改源码就能增强功能 |
| 模板方法模式 | JdbcTemplate、RestTemplate |
固定骨架,可变步骤留给子类 |
| 观察者模式 | 事件机制 ApplicationEvent |
一处发布,多处监听 |
| 适配器模式 | HandlerAdapter、MessageConverter |
让不兼容的接口能协同工作 |
| 策略模式 | Resource 接口、InstantiationStrategy |
同一接口,不同实现策略 |
| 责任链模式 | Filter 链、Interceptor 链 |
请求沿着链条依次处理 |
| 装饰器模式 | BeanWrapper、HttpRequestDecorator |
动态增强对象功能 |
1.2 深度解析
1.2.1 工厂模式(Spring 心脏)
工厂模式是 Spring 的基石。你天天写 @Component、@Service,有没有想过这些对象是谁创建的?就是 BeanFactory。

上图展示了 Spring 工厂体系的层次结构:
BeanFactory:最顶层的工厂接口,提供了getBean()这样的基本能力,属于 "懒加载",用到Bean的时候才创建。ApplicationContext:BeanFactory的超集,除了创建Bean,还集成了国际化、事件发布、资源加载等功能。我们平时用的@SpringBootApplication启动后拿到的就是它。- 具体实现有
ClassPathXmlApplicationContext(XML 配置时代)和AnnotationConfigApplicationContext(注解时代),不同的工厂实现从不同的配置源读取Bean定义,但对外暴露的getBean()接口完全一致。
这就是工厂模式的核心思想:把对象的创建逻辑封装在工厂内部,调用方不需要关心对象是怎么 new 出来的。
1.2.2 单例模式(Spring Bean 默认作用域)
Spring 的单例不是传统意义上的 "写个 private 构造器 + static 实例" 那种单例,而是 容器级别的单例------由容器来保证同一个 id 的 Bean 只创建一次。
java
// Spring 的单例实现(DefaultSingletonBeanRegistry 源码简化)
public class DefaultSingletonBeanRegistry {
// 一级缓存:存放完全初始化好的单例 Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
public Object getSingleton(String beanName) {
Object singleton = singletonObjects.get(beanName);
if (singleton == null) {
singleton = createBean(beanName);
singletonObjects.put(beanName, singleton);
}
return singleton;
}
}
Spring 用 三级缓存 来解决单例 Bean 的循环依赖问题,这个在面试中经常和单例模式一起追问。
注意:Spring 的单例是非线程安全的。因为单例 Bean 在容器中只有一个实例,如果 Bean 里有可变状态,多线程并发访问就会出问题。所以 Spring 官方推荐 Bean 设计为 无状态 的。
1.2.3 代理模式(AOP 灵魂)
这个应该是大家最熟悉的,Spring AOP 的两种实现方式------JDK 动态代理和 CGLIB 代理,本质上都是代理模式的应用。
java
// JDK 动态代理示例(Spring AOP 的原理简化)
public class JdkProxyDemo implements InvocationHandler {
private Object target;
public Object createProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置通知
System.out.println("Before: " + method.getName());
// 执行目标方法
Object result = method.invoke(target, args);
// 后置通知
System.out.println("After: " + method.getName());
return result;
}
}
代理模式的精髓在于:不修改原有代码的前提下,对功能进行增强。不管是日志、事务、权限控制,统统可以通过代理来织入,这就是 AOP 能成立的基础。
1.2.4 模板方法模式(JdbcTemplate 一族)
模板方法模式在 Spring 中用得非常多,但凡名字里带 Template 的,基本都是。
java
// JdbcTemplate 的典型用法
jdbcTemplate.query("SELECT * FROM user WHERE id = ?",
(rs, rowNum) -> { // ←你只需要关注这一部分
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
return user;
},
1L // 参数
);
// 连接获取、Statement 创建、异常处理、资源关闭 ------ 全部由模板搞定
模板方法模式的套路是:父类定义算法骨架(固定流程),子类实现可变步骤。JdbcTemplate 把 JDBC 那套繁琐的 try-catch-finally 流程全部封装好了,只需要告诉它 "SQL 是什么" 和 "结果怎么映射",其他的一概不用操心。
Spring 中类似的还有 RestTemplate、JmsTemplate、RedisTemplate,套路完全一样。
1.2.5 观察者模式(事件机制)
Spring 的事件机制就是标准的观察者模式:一个事件发布者,N 个事件监听者。
java
// 1. 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private Order order;
public OrderCreatedEvent(Object source, Order order) {
super(source);
this.order = order;
}
}
// 2. 发布事件
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder(Order order) {
// 业务逻辑...
publisher.publishEvent(new OrderCreatedEvent(this, order));
}
}
// 3. 监听事件(可以有多个监听者)
@Component
public class EmailNotifier {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 发邮件通知
}
}
@Component
public class PointsService {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 积分奖励
}
}
这个模式在实际项目中非常有用。下单之后要发短信、送积分、更新库存......如果全写在一个方法里,耦合度爆炸。用事件机制解耦之后,各干各的,互不影响,新增功能只需要加个 @EventListener 就行。
1.2.6 适配器模式(Spring MVC 的核心)
Spring MVC 中 HandlerAdapter 就是典型的适配器模式。

上图的逻辑是:
DispatcherServlet拿到一个Handler后,不知道它具体是什么类型(可能是传统Controller接口,可能是@RequestMapping注解方法,也可能是HttpRequestHandler)。- 于是
DispatcherServlet不直接调用Handler,而是找到对应的HandlerAdapter,由适配器来负责调用。每种Handler都有自己专属的适配器实现。 - 这样
DispatcherServlet只需要面向HandlerAdapter这个统一接口编程,完全不用关心底层Handler的差异。
这就是适配器模式的价值:让原本不兼容的接口能够协同工作。
1.2.7 策略模式
Spring 中策略模式的应用也很多,比如资源加载:
java
// Resource 接口有多种实现策略
Resource resource1 = new ClassPathResource("config.xml"); // 类路径
Resource resource2 = new FileSystemResource("/etc/config.xml"); // 文件系统
Resource resource3 = new UrlResource("https://example.com/config.xml"); // 网络
// AbstractApplicationContext 中的资源加载策略
public interface ResourceLoader {
Resource getResource(String location);
}
调用方只面向 Resource 接口编程,至于底层是从类路径读、从磁盘读、还是从网络读,由具体的策略实现来决定。