偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

聊聊Spring中最常用的十種設(shè)計(jì)模式

開發(fā) 前端
作為一名有多年開發(fā)經(jīng)驗(yàn)的老司機(jī),每次翻看Spring源碼都讓我感嘆:"這哪是框架,分明是設(shè)計(jì)模式的百科全書!"有些小伙伴在工作中可能只會(huì)用@Autowired,卻不知背后藏著多少精妙設(shè)計(jì)。今天這篇文章跟大家一起聊聊Spring中最常用的10種設(shè)計(jì)模式,希望對(duì)你會(huì)有所幫助。

前言

作為一名有多年開發(fā)經(jīng)驗(yàn)的老司機(jī),每次翻看Spring源碼都讓我感嘆:"這哪是框架,分明是設(shè)計(jì)模式的百科全書!"

有些小伙伴在工作中可能只會(huì)用@Autowired,卻不知背后藏著多少精妙設(shè)計(jì)。

今天這篇文章跟大家一起聊聊Spring中最常用的10種設(shè)計(jì)模式,希望對(duì)你會(huì)有所幫助。

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

場景:處理重復(fù)流程但允許細(xì)節(jié)變化Spring應(yīng)用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;
    }
    
    // 留給子類實(shí)現(xiàn)的鉤子方法
    protected abstract Connection getConnection();
    protected abstract Object mapResult(ResultSet rs);
}

為什么用

  • 復(fù)用資源管理(連接獲取/釋放)等通用邏輯
  • 允許子類只關(guān)注業(yè)務(wù)差異(如結(jié)果映射)思考:當(dāng)你寫重復(fù)流程時(shí),想想能否抽出模板骨架

2.工廠模式:對(duì)象出生管理局

場景:解耦對(duì)象創(chuàng)建與使用Spring應(yīng)用BeanFactory核心接口

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

// 實(shí)現(xiàn)類:DefaultListableBeanFactory
public class UserService {
    // 使用者無需關(guān)心Bean如何創(chuàng)建
    @Autowired 
    private OrderService orderService; 
}

設(shè)計(jì)精髓

  • 隱藏復(fù)雜的對(duì)象初始化過程(如循環(huán)依賴處理)
  • 統(tǒng)一管理對(duì)象生命周期(單例/原型等作用域)類比:就像點(diǎn)外賣不需要知道廚師怎么做菜

3.代理模式:隱形護(hù)衛(wèi)

場景:無侵入增強(qiáng)對(duì)象功能

Spring應(yīng)用:AOP動(dòng)態(tài)代理

// JDK動(dòng)態(tài)代理示例
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("【日志】調(diào)用方法: " + method.getName());
        return method.invoke(target, args); // 執(zhí)行原方法
    }
}

// Spring中通過@Aspect實(shí)現(xiàn)類似功能
@Aspect
@Component
publicclass LogAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logMethodCall(JoinPoint jp) {
        System.out.println("調(diào)用方法: " + jp.getSignature().getName());
    }
}

動(dòng)態(tài)代理兩板斧

  • JDK代理:基于接口(要求目標(biāo)類實(shí)現(xiàn)接口)
  • CGLIB代理:基于繼承(可代理普通類)價(jià)值:業(yè)務(wù)邏輯與橫切關(guān)注點(diǎn)(日志/事務(wù)等)徹底解耦

4.單例模式:全局唯一指揮官

場景:減少資源消耗,保證全局一致性

Spring實(shí)現(xiàn):Bean默認(rèn)作用域

// 源碼片段:AbstractBeanFactory
public Object getBean(String name) {
    Object bean = getSingleton(name); // 先查緩存
    if (bean == null) {
        bean = createBean(name);      // 不存在則創(chuàng)建
        addSingleton(name, bean);     // 放入緩存
    }
    return bean;
}

關(guān)鍵設(shè)計(jì)

  • 三級(jí)緩存解決循環(huán)依賴(singletonObjects, earlySingletonObjects, singletonFactories)
  • 并發(fā)安全通過synchronized+雙重檢查鎖定實(shí)現(xiàn)警示:切忌在單例Bean中保存狀態(tài)變量!

5.觀察者模式:事件廣播網(wǎng)

場景:解耦事件生產(chǎn)者和消費(fèi)者

Spring應(yīng)用ApplicationEvent機(jī)制

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

// 2. 發(fā)布事件
@Service
publicclass OrderService {
    @Autowired ApplicationEventPublisher publisher;
    
    public void createOrder(Order order) {
        // 業(yè)務(wù)邏輯...
        publisher.publishEvent(new OrderCreatedEvent(order));
    }
}

// 3. 監(jiān)聽事件
@Component
publicclass EmailListener {
    @EventListener
    public void handleOrderEvent(OrderCreatedEvent event) {
        // 發(fā)送郵件通知
    }
}

優(yōu)勢

  • 事件源與監(jiān)聽器完全解耦
  • 支持異步處理(加@Async注解即可)

6.策略模式:算法切換器

場景:動(dòng)態(tài)選擇算法實(shí)現(xiàn)

Spring應(yīng)用Resource資源加載

// 資源加載策略族
Resource res1 = new ClassPathResource("config.xml"); // 類路徑策略
Resource res2 = new UrlResource("http://config.com");// 網(wǎng)絡(luò)策略
Resource res3 = new FileSystemResource("/opt/config");// 文件系統(tǒng)策略

// 統(tǒng)一調(diào)用接口
InputStream is = res1.getInputStream();

源碼設(shè)計(jì)亮點(diǎn)

  • Resource接口統(tǒng)一抽象
  • 通過ResourceLoader自動(dòng)選擇策略應(yīng)用場景:支付方式切換(微信/支付寶/銀聯(lián))

7.適配器模式:接口轉(zhuǎn)換器

場景:兼容不兼容的接口

Spring應(yīng)用: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); // 統(tǒng)一適配調(diào)用
    }
}

// 實(shí)際Spring源碼中處理了:
// 1. @Controller注解類 2. HttpRequestHandler 3. Servlet實(shí)現(xiàn)等

價(jià)值

  • 讓DispatcherServlet無需關(guān)心Controller具體類型
  • 新增Controller類型只需擴(kuò)展適配器

8.裝飾器模式:功能增強(qiáng)包

場景:動(dòng)態(tài)添加功能

Spring應(yīng)用HttpServletRequest包裝

// 典型應(yīng)用:緩存請(qǐng)求體
ContentCachingRequestWrapper wrappedRequest = 
    new ContentCachingRequestWrapper(rawRequest);

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

源碼實(shí)現(xiàn)

public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
    private ByteArrayOutputStream cachedContent;
    
    @Override
    public ServletInputStream getInputStream() {
        // 裝飾原方法:緩存流數(shù)據(jù)
    }
}

設(shè)計(jì)本質(zhì):通過包裝器在不修改原對(duì)象基礎(chǔ)上增強(qiáng)功能

9.建造者模式:復(fù)雜對(duì)象組裝工

場景:分步構(gòu)建復(fù)雜對(duì)象

Spring應(yīng)用BeanDefinitionBuilder

// 構(gòu)建復(fù)雜的Bean定義
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(UserService.class);
builder.addPropertyValue("maxRetry", 3);
builder.setInitMethodName("init");
builder.setScope(BeanDefinition.SCOPE_SINGLETON);

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

對(duì)比傳統(tǒng)構(gòu)造

  • 解決多參數(shù)構(gòu)造的混亂(尤其可選參數(shù)多時(shí))
  • 構(gòu)建過程更加清晰可讀

10 責(zé)任鏈模式:攔截器的骨架設(shè)計(jì)

場景:解耦多步驟處理流程

Spring應(yīng)用HandlerInterceptor攔截器鏈

// Spring MVC核心執(zhí)行鏈
publicclass HandlerExecutionChain {
    privatefinal List<HandlerInterceptor> interceptors = new ArrayList<>();
    
    // 執(zhí)行前置處理(責(zé)任鏈核心)
    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;
    }
}

實(shí)戰(zhàn)配置

@Configuration
publicclass WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 構(gòu)建責(zé)任鏈
        registry.addInterceptor(new LogInterceptor()).order(1);
        registry.addInterceptor(new AuthInterceptor()).order(2);
        registry.addInterceptor(new RateLimitInterceptor()).order(3);
    }
}

// 獨(dú)立攔截器實(shí)現(xiàn)
publicclass AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
        if (!checkToken(req.getHeader("Authorization"))) {
            res.sendError(401); // 認(rèn)證失敗
            returnfalse; // 中斷鏈
        }
        returntrue; // 放行
    }
}

設(shè)計(jì)價(jià)值

  • 開閉原則:新增攔截器無需修改現(xiàn)有代碼
  • 單一職責(zé):每個(gè)攔截器只關(guān)注單一功能
  • 動(dòng)態(tài)編排:通過order()靈活調(diào)整執(zhí)行順序
  • 流程控制:任意節(jié)點(diǎn)可中斷或繼續(xù)傳遞


典型反模式:在攔截器中注入其他攔截器,這將破壞責(zé)任鏈獨(dú)立性,導(dǎo)致循環(huán)依賴!

總結(jié)

  • 解耦的藝術(shù)工廠模式解耦創(chuàng)建/使用,觀察者模式解耦事件/處理
  • 擴(kuò)展性的智慧策略模式支持算法擴(kuò)展,裝飾器模式支持功能擴(kuò)展
  • 復(fù)雜性的封裝模板方法封裝流程,建造者模式封裝構(gòu)建
  • 性能的權(quán)衡單例模式減少資源消耗,代理模式按需增強(qiáng)

最后送給小伙伴們的建議:不要為了用模式而用模式。

就像Spring的作者Rod Johnson說的:"優(yōu)雅的代碼不是模式的堆砌,而是恰到好處的抽象。"

責(zé)任編輯:武曉燕 來源: 蘇三說技術(shù)
相關(guān)推薦

2025-04-25 07:10:00

GenAIAI工具人工智能

2024-12-11 08:20:57

設(shè)計(jì)模式源碼

2023-05-15 15:29:13

設(shè)計(jì)模式JavaScript

2020-08-16 20:36:21

滲透測試漏洞網(wǎng)絡(luò)攻擊

2024-10-14 08:39:29

工廠模式策略模式代碼

2024-09-03 10:40:38

2016-10-21 19:44:08

數(shù)據(jù)科學(xué)家算法

2023-07-19 11:19:37

AI項(xiàng)目人工智能

2024-01-24 13:14:00

Python內(nèi)置函數(shù)工具

2024-01-22 08:15:42

API協(xié)議設(shè)計(jì)

2022-08-26 16:21:47

數(shù)據(jù)分析工具運(yùn)營

2025-02-10 08:30:00

JavaScrip開發(fā)設(shè)計(jì)模式

2022-01-09 18:32:03

MySQL SQL 語句數(shù)據(jù)庫

2024-01-22 13:53:00

Linux環(huán)境變量

2022-06-16 11:01:22

數(shù)據(jù)庫SQL

2024-11-08 13:34:24

2024-09-02 10:07:52

2024-03-26 13:35:19

模型架構(gòu)框架

2024-02-28 18:01:20

IDEAIDEtry

2022-10-11 11:38:23

Spring
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)