聊聊Spring中最常用的10种设计模式

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构

RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRMAI大模型、IoT物联网等功能:

  • 多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • 微服务:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本 

来源:苏三说技术


前言

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

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

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

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

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

场景 :处理重复流程但允许细节变化Spring应用 :JdbcTemplateRestTemplate

// 伪代码展示模板方法核心
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. 允许子类只关注业务差异(如结果映射)思考 :当你写重复流程时,想想能否抽出模板骨架

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

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说的:"优雅的代码不是模式的堆砌,而是恰到好处的抽象 。"

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


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值