SpringBoot如何通過Map實現(xiàn)策略模式
前言
策略模式是一種行為設(shè)計模式,它允許在運行時選擇算法的行為。在Spring框架中,我們可以利用@Resource
注解和Map
集合來優(yōu)雅地實現(xiàn)策略模式。
在Spring框架中,當(dāng)你使用@Resource
注解注入一個Map<String, T>
時,Spring會自動將所有類型為T的bean收集到這個Map中,其中:
- Key是bean的名稱
- Value是bean實例
底層機制解析
Spring的集合類型自動裝配
Spring框架對集合類型的依賴注入有特殊處理:
- 當(dāng)注入List時,會收集所有類型為T的bean
- 當(dāng)注入Map<String, T>時,會收集所有類型為T的bean,并以bean名稱作為key
@Resource注解的行為
@Resource
注解默認按名稱裝配,但當(dāng)目標(biāo)是一個Map時,Spring會特殊處理:
- 如果Map的key是String類型,value是某個接口/類
- Spring會查找所有實現(xiàn)該接口/繼承該類的bean
- 將這些bean以"bean名稱->bean實例"的形式放入Map
實現(xiàn)原理
Spring在依賴注入時的處理流程:
- 發(fā)現(xiàn)字段/方法參數(shù)是Map<String, T>類型
- 在應(yīng)用上下文中查找所有類型為T的bean
- 創(chuàng)建一個新的Map實例
- 遍歷找到的所有bean,以bean名稱作為key,bean實例作為value放入Map
- 將這個Map注入到目標(biāo)字段/參數(shù)中
使用
直接使用Map<String,T>
我們直接定義一個Controller,并且在Controller中使用@Resource
和Map<String,T>
@RestController @RequestMapping("/test") public class TestController { @Resource private Map<String, Object> beanMap = new ConcurrentHashMap<>(); public void beanMap() { System.out.println(beanMap.size()); } }
驗證:可以看到map中存了項目中所有的bean對象
指定Map中的bean類型
在實際的開發(fā)中,我們希望Map中只是存儲需要的Bean,并且Controller中可以根據(jù)beanName進行轉(zhuǎn)發(fā)到不同的Service中,步驟如下:
定義策略接口
public interface PaymentStrategy { void pay(); }
定義實現(xiàn)類
@Service("ALI") @Slf4j public class AliStrategyService implements PaymentStrategy { @Override public void pay() { log.info("使用支付寶支付"); } } @Service("WX") @Slf4j public class WxStrategyService implements PaymentStrategy { @Override public void pay() { log.info("使用微信支付"); } }
策略使用
@RestController @RequestMapping("/test") public class TestController { @Resource private Map<String, PaymentStrategy> beanMap = new ConcurrentHashMap<>(); public void beanMap() { PaymentStrategy wx = beanMap.get("WX"); wx.pay(); PaymentStrategy ali = beanMap.get("ALI"); ali.pay(); } }
驗證
可以看到map中,就只有兩個Bean,并且key就是我們通過@Service(value)定義的名稱
自定義注解實現(xiàn)
自定義一個注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Component public @interface PaymentType { String value(); }
注解替換:將原有的@Service(value)
替換為@PaymentType (value)
,比如:
@PaymentType("CARD") @Slf4j public class CardStrategyService implements PaymentStrategy { @Override public void pay() { log.info("使用銀行卡支付"); } }
**意義:**可以更好表示策略模式,讓其他開發(fā)人員一眼可以看出當(dāng)前的Service
使用了策略模式
到此這篇關(guān)于SpringBoot通過Map實現(xiàn)天然的策略模式的文章就介紹到這了,更多相關(guān)SpringBoot策略模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Data JPA實現(xiàn)動態(tài)條件與范圍查詢實例代碼
本篇文章主要介紹了Spring Data JPA實現(xiàn)動態(tài)條件與范圍查詢實例代碼,非常具有實用價值,需要的朋友可以參考下2017-06-06springboot配合Thymeleaf完美實現(xiàn)遍歷功能
Thymeleaf顯然是一個開發(fā)頁面的技術(shù),現(xiàn)在各種前端技術(shù)層出不窮,比如現(xiàn)在主流的Vue、React、AngularJS等。這篇文章主要介紹了springboot配合Thymeleaf完美實現(xiàn)遍歷,需要的朋友可以參考下2021-09-09使用Springboot根據(jù)配置文件動態(tài)注入接口實現(xiàn)類
這篇文章主要介紹了使用Springboot根據(jù)配置文件動態(tài)注入接口實現(xiàn)類,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08