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

向量数据库大模型云通信

picture.image

苏三的宝藏网站(面试题、简历模版、项目实战什么都有):http://www.susan.net.cn

大家好,我是苏三,又跟大家见面。

前言

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

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

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

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. 允许子类只关注业务差异(如结果映射)

思考 :当你写重复流程时,想想能否抽出模板骨架

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());  

对比传统构造

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

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

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; // 继续执行  
    }  
}  

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

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

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

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

最后欢迎加入苏三的星球,你将获得:商城微服务实战、AI开发项目课程、苏三AI项目、秒杀系统实战、商城系统实战、秒杀系统实战、代码生成工具、系统设计、性能优化、技术选型、底层原理、Spring源码解读、工作经验分享、痛点问题、面试八股文等多个优质专栏。

还有1V1答疑、修改简历、职业规划、送书活动、技术交流。

扫描下方二维码,即可加入星球(非常有价值的一次决定):

picture.image

目前星球已经更新了5200+篇优质内容,还在持续爆肝中.....

星球已经被官方推荐了3次,收到了小伙伴们的一致好评。戳我加入学习,已有1700+小伙伴加入学习。

最后推荐一下我的技术专栏《性能优化35讲》,里面包含了:接口调用、Java、JVM、并发编程、MySQL、Redis、ElasticSearch、Spring、SpringBoot等多个性能优化技巧。无论在工作,还是在面试中,都会经常遇到,非常有参考价值。

picture.image

picture.image

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
如何利用云原生构建 AIGC 业务基石
AIGC即AI Generated Content,是指利用人工智能技术来生成内容,AIGC也被认为是继UGC、PGC之后的新型内容生产方式,AI绘画、AI写作等都属于AIGC的分支。而 AIGC 业务的部署也面临着异构资源管理、机器学习流程管理等问题,本次分享将和大家分享如何使用云原生技术构建 AIGC 业务。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论