⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 苏三说技术 「苏三」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

前言

作为一名有多年开发经验的老司机,每次翻看Spring源码都让我感叹:”这哪是框架,分明是设计模式的百科全书!”

有些小伙伴在工作中可能只会用@Autowired,却不知背后藏着多少精妙设计。

今天这篇文章跟大家一起聊聊Spring中最常用的10种设计模式,希望对你会有所帮助。

1 模板方法模式:流程骨架大师

场景:处理重复流程但允许细节变化
Spring应用:JdbcTemplate、RestTemplate等

// 伪代码展示模板方法核心
publicabstractclass JdbcTemplate {
// 定义算法骨架(不可重写)
public final Object execute(String sql) {
Connection conn = getConnection(); // 抽象方法
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
Object result = mapResult(rs); // 抽象方法
releaseResources(conn, stmt, rs);
return result;
}

// 留给子类实现的钩子方法
protected abstract Connection getConnection();
protected abstract Object mapResult(ResultSet rs);
}

为什么用:

  1. 复用资源管理(连接获取/释放)等通用逻辑
  2. 允许子类只关注业务差异(如结果映射)
    思考:当你写重复流程时,想想能否抽出模板骨架

2 工厂模式:对象出生管理局

场景:解耦对象创建与使用
Spring应用:BeanFactory核心接口

public interface BeanFactory {
Object getBean(String name);
<T> T getBean(Class<T> requiredType);
}

// 实现类:DefaultListableBeanFactory
public class UserService {
// 使用者无需关心Bean如何创建
@Autowired
private OrderService orderService;
}

设计精髓:

  • 隐藏复杂的对象初始化过程(如循环依赖处理)
  • 统一管理对象生命周期(单例/原型等作用域)
    类比:就像点外卖不需要知道厨师怎么做菜

3 代理模式:隐形护卫

场景:无侵入增强对象功能

Spring应用:AOP动态代理

// JDK动态代理示例
publicclass LogProxy 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) {
System.out.println("【日志】调用方法: " + method.getName());
return method.invoke(target, args); // 执行原方法
}
}

// Spring中通过@Aspect实现类似功能
@Aspect
@Component
publicclass LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logMethodCall(JoinPoint jp) {
System.out.println("调用方法: " + jp.getSignature().getName());
}
}

动态代理两板斧:

  1. JDK代理:基于接口(要求目标类实现接口)
  2. CGLIB代理:基于继承(可代理普通类)
    价值:业务逻辑与横切关注点(日志/事务等)彻底解耦

4 单例模式:全局唯一指挥官

场景:减少资源消耗,保证全局一致性

Spring实现:Bean默认作用域

// 源码片段:AbstractBeanFactory
public Object getBean(String name) {
Object bean = getSingleton(name); // 先查缓存
if (bean == null) {
bean = createBean(name); // 不存在则创建
addSingleton(name, bean); // 放入缓存
}
return bean;
}

关键设计:

  • 三级缓存解决循环依赖(singletonObjects, earlySingletonObjects, singletonFactories)
  • 并发安全通过synchronized+双重检查锁定实现
    警示:切忌在单例Bean中保存状态变量!

5 观察者模式:事件广播网

场景:解耦事件生产者和消费者

Spring应用:ApplicationEvent机制

// 1. 定义事件
publicclass OrderCreatedEvent extends ApplicationEvent {
public OrderCreatedEvent(Order source) {
super(source);
}
}

// 2. 发布事件
@Service
publicclass OrderService {
@Autowired ApplicationEventPublisher publisher;

public void createOrder(Order order) {
// 业务逻辑...
publisher.publishEvent(new OrderCreatedEvent(order));
}
}

// 3. 监听事件
@Component
publicclass EmailListener {
@EventListener
public void handleOrderEvent(OrderCreatedEvent event) {
// 发送邮件通知
}
}

优势:

  • 事件源与监听器完全解耦
  • 支持异步处理(加@Async注解即可)

6 策略模式:算法切换器

场景:动态选择算法实现

Spring应用:Resource资源加载

// 资源加载策略族
Resource res1 = new ClassPathResource("config.xml"); // 类路径策略
Resource res2 = new UrlResource("http://config.com");// 网络策略
Resource res3 = new FileSystemResource("/opt/config");// 文件系统策略

// 统一调用接口
InputStream is = res1.getInputStream();

源码设计亮点:

  • Resource接口统一抽象
  • 通过ResourceLoader自动选择策略
    应用场景:支付方式切换(微信/支付宝/银联)

7 适配器模式:接口转换器

场景:兼容不兼容的接口

Spring应用:Spring MVC的HandlerAdapter

// 伪代码:处理多种Controller
publicclass RequestMappingHandlerAdapter implements HandlerAdapter {

public boolean supports(Object handler) {
return handler instanceof Controller;
}

public ModelAndView handle(HttpRequest req, HttpResponse res, Object handler) {
Controller controller = (Controller) handler;
return controller.handleRequest(req, res); // 统一适配调用
}
}

// 实际Spring源码中处理了:
// 1. @Controller注解类 2. HttpRequestHandler 3. Servlet实现等

价值:

  • 让DispatcherServlet无需关心Controller具体类型
  • 新增Controller类型只需扩展适配器

8 装饰器模式:功能增强包

场景:动态添加功能

Spring应用:HttpServletRequest包装

// 典型应用:缓存请求体
ContentCachingRequestWrapper wrappedRequest =
new ContentCachingRequestWrapper(rawRequest);

// 可在filter中多次读取body
byte[] body = wrappedRequest.getContentAsByteArray();

源码实现:

public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
private ByteArrayOutputStream cachedContent;

@Override
public ServletInputStream getInputStream() {
// 装饰原方法:缓存流数据
}
}

设计本质:通过包装器在不修改原对象基础上增强功能

9 建造者模式:复杂对象组装工

场景:分步构建复杂对象

Spring应用:BeanDefinitionBuilder

// 构建复杂的Bean定义
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(UserService.class);
builder.addPropertyValue("maxRetry", 3);
builder.setInitMethodName("init");
builder.setScope(BeanDefinition.SCOPE_SINGLETON);

// 注册到容器
registry.registerBeanDefinition("userService", builder.getBeanDefinition());

对比传统构造:

  • 解决多参数构造的混乱(尤其可选参数多时)
  • 构建过程更加清晰可读

10 责任链模式:拦截器的骨架

MVC拦截器实现:

// 伪代码:拦截器链执行
publicclass HandlerExecutionChain {
privatefinal List<HandlerInterceptor> interceptors = new ArrayList<>();

boolean applyPreHandle(HttpRequest req, HttpResponse res) {
for (HandlerInterceptor interceptor : interceptors) {
if (!interceptor.preHandle(req, res)) returnfalse; // 中断链
}
returntrue;
}
}

// 自定义拦截器
publicclass LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res) {
System.out.println("请求进入: " + req.getRequestURI());
returntrue; // 继续执行
}
}

拦截器的骨架设计

场景:解耦多步骤处理流程

Spring应用:HandlerInterceptor拦截器链

// Spring MVC核心执行链
publicclass HandlerExecutionChain {
privatefinal List<HandlerInterceptor> interceptors = new ArrayList<>();

// 执行前置处理(责任链核心)
public boolean applyPreHandle(HttpServletRequest request,
HttpServletResponse response) {
for (int i = 0; i < interceptors.size(); i++) {
HandlerInterceptor interceptor = interceptors.get(i);
// 任意拦截器返回false则中断链条
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, i); // 清理已完成
returnfalse;
}
}
returntrue;
}
}

实战配置:

@Configuration
publicclass WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 构建责任链
registry.addInterceptor(new LogInterceptor()).order(1);
registry.addInterceptor(new AuthInterceptor()).order(2);
registry.addInterceptor(new RateLimitInterceptor()).order(3);
}
}

// 独立拦截器实现
publicclass AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
if (!checkToken(req.getHeader("Authorization"))) {
res.sendError(401); // 认证失败
returnfalse; // 中断链
}
returntrue; // 放行
}
}

设计价值:

  1. 开闭原则:新增拦截器无需修改现有代码
  2. 单一职责:每个拦截器只关注单一功能
  3. 动态编排:通过order()灵活调整执行顺序
  4. 流程控制:任意节点可中断或继续传递

典型反模式:在拦截器中注入其他拦截器,这将破坏责任链独立性,导致循环依赖!

总结

  1. 解耦的艺术
    工厂模式解耦创建/使用,观察者模式解耦事件/处理
  2. 扩展性的智慧
    策略模式支持算法扩展,装饰器模式支持功能扩展
  3. 复杂性的封装
    模板方法封装流程,建造者模式封装构建
  4. 性能的权衡
    单例模式减少资源消耗,代理模式按需增强

最后送给小伙伴们的建议:不要为了用模式而用模式。

就像Spring的作者Rod Johnson说的:”优雅的代码不是模式的堆砌,而是恰到好处的抽象。”

当你下次写代码感到别扭时,不妨想想这些经典模式,或许能豁然开朗。

文章目录
  1. 1. 前言
  2. 2. 1 模板方法模式:流程骨架大师
  3. 3. 2 工厂模式:对象出生管理局
  4. 4. 3 代理模式:隐形护卫
  5. 5. 4 单例模式:全局唯一指挥官
  6. 6. 5 观察者模式:事件广播网
  7. 7. 6 策略模式:算法切换器
  8. 8. 7 适配器模式:接口转换器
  9. 9. 8 装饰器模式:功能增强包
  10. 10. 9 建造者模式:复杂对象组装工
  11. 11. 10 责任链模式:拦截器的骨架
    1. 11.0.1. 拦截器的骨架设计
  • 12. 总结