最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot如何通過Map實現(xiàn)天然的策略模式

 更新時間:2026年03月02日 09:52:04   作者:一恍過去  
文章介紹了如何在Spring框架中使用@Resource注解和Map集合來實現(xiàn)策略模式,并詳細解釋了Spring如何處理集合類型的依賴注入,通過這種方式,可以在運行時動態(tài)地選擇算法的行為,使得代碼更加靈活和可擴展

前言

策略模式是一種行為設計模式,它允許在運行時選擇算法的行為。在Spring框架中,我們可以利用@Resource注解和Map集合來優(yōu)雅地實現(xiàn)策略模式。

在Spring框架中,當你使用@Resource注解注入一個Map<String, T>或List時,Spring會自動將所有類型為T的bean收集到這個Map或者List集合中,其中:

Map

  • Key是bean的名稱
  • Value是bean實例

List

  • bean實例

底層機制解析

Spring的集合類型自動裝配

Spring框架對集合類型的依賴注入有特殊處理:

  • 當注入List時,會收集所有類型為T的bean
  • 當注入Map<String, T>時,會收集所有類型為T的bean,并以bean名稱作為key

@Resource注解的行為

@Resource注解默認按名稱裝配,但當目標是一個Map時,Spring會特殊處理:

  • 如果Map的key是String類型,value是某個接口/類
  • Spring會查找所有實現(xiàn)該接口/繼承該類的bean
  • 將這些bean以"bean名稱->bean實例"的形式放入Map

實現(xiàn)原理

Spring在依賴注入時的處理流程:

  • 發(fā)現(xiàn)字段/方法參數(shù)是Map<String, T>類型
  • 在應用上下文中查找所有類型為T的bean
  • 創(chuàng)建一個新的Map實例
  • 遍歷找到的所有bean,以bean名稱作為key,bean實例作為value放入Map
  • 將這個Map注入到目標字段/參數(shù)中

使用

直接使用Map<String,T>

我們直接定義一個Controller,并且在Controller中使用@ResourceMap<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進行轉發(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ā)人員一眼可以看出當前的Service使用了策略模式

結合List進行優(yōu)化

在上面直接使用Map來注入Bean的場景下,如果Service(“xxName”)的名稱和某個枚舉或者常量一致的情況,并且會在多處使用,那么枚舉或者常量變更后Service(“xxName”)沒有修改到就容易出現(xiàn)問題(啟動不會報錯,容易忽略修改);

  • 可以結合List的方式來解決這個問題,比如存在常量如下:
public interface PayWayConstants {
    String ALI_PAY = "ALI";

    String WX_PAY = "WX";
}
  • PaymentStrategy 接口添加一個公共的方法: getWay(),改造后如下:

@Service(“ALI”)中不再需要寫value值

// 接口
public interface PaymentStrategy {
	String getWay();
	
    void pay();
}


	// 各個實現(xiàn)類
	@Service
	@Slf4j
	public class AliStrategyService implements PaymentStrategy {
		@Override
	    public String getWay() {
	       return PayWayConstants.ALI_PAY;
	    }
	
	    @Override
	    public void pay() {
	        log.info("使用支付寶支付");
	    }
	}


	@Service
	@Slf4j
	public class WxStrategyService implements PaymentStrategy {
		@Override
	    public String getWay() {
	      return PayWayConstants.WX_PAY;
	    }
	    
	    @Override
	    public void pay() {
	        log.info("使用微信支付");
	    }
	}

  • Bean的注入調整,單獨使用一個類來加載這些策略模式的Bean對象
@Component
public class PaymentStrategyComponent {

    private Map<String, PaymentStrategy> beanMap = new ConcurrentHashMap<>();

    @Resource
    private List<PaymentStrategy> list;

    @PostConstruct
    public void init() {
        for (PaymentStrategy service : list) {
            beanMap.put(service.getWay(), service);
            log.info("Registered: {}", service.getWay());
        }
    }

    public PaymentStrategy getPaymentStrategy(String way) {
        return beanMap.get(way);
    }
}
  • 策略使用,使用時就可以使用常量來代替字符串的形式,這樣便于后期常量或者枚舉值的變更
@RestController
@RequestMapping("/test")
public class TestController {

    @Resource
    private PaymentStrategyComponent strategyComponent;
    
    public void beanMap() {
        PaymentStrategy wx = strategyComponent.getPaymentStrategy(PayWayConstants.WX_PAY);
        wx.pay();
        PaymentStrategy ali = strategyComponent.getPaymentStrategy(PayWayConstants.ALI_PAY);
        ali.pay();
    }
}

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 詳解Java實現(xiàn)緩存(LRU,FIFO)

    詳解Java實現(xiàn)緩存(LRU,FIFO)

    本篇文章主要介紹了詳解Java實現(xiàn)緩存(LRU,FIFO) ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • MyBatis-Plus實現(xiàn)條件查詢的三種格式例舉詳解

    MyBatis-Plus實現(xiàn)條件查詢的三種格式例舉詳解

    本文主要介紹了MyBatis-Plus三中條件查詢格式的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • 基于SpringBoot?使用?Flink?收發(fā)Kafka消息的示例詳解

    基于SpringBoot?使用?Flink?收發(fā)Kafka消息的示例詳解

    這篇文章主要介紹了基于SpringBoot?使用?Flink?收發(fā)Kafka消息,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • idea創(chuàng)建Spring項目的方法步驟(圖文)

    idea創(chuàng)建Spring項目的方法步驟(圖文)

    這篇文章主要介紹了idea創(chuàng)建Spring項目的方法步驟(圖文),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • java實現(xiàn)簡單解析XML文件功能示例

    java實現(xiàn)簡單解析XML文件功能示例

    這篇文章主要介紹了java實現(xiàn)簡單解析XML文件功能,結合實例形式分析了java針對xml文件的讀取、遍歷節(jié)點及輸出等相關操作技巧,需要的朋友可以參考下
    2017-10-10
  • Spring boot 4 搞懂MyBatis-Plus的用法解析

    Spring boot 4 搞懂MyBatis-Plus的用法解析

    MyBatis-Plus是MyBatis的增強工具,提供了CRUD操作和自動填充等功能,通過繼承BaseMapper接口,可以快速實現(xiàn)數(shù)據(jù)庫操作,MyBatis-Plus提供了多種插件,如分頁、樂觀鎖、多租戶等,以增強系統(tǒng)的功能和性能,本文介紹Spring boot 4 搞懂MyBatis-Plus的用法,感興趣的朋友一起看看吧
    2026-01-01
  • SpringMVC使用hibernate-validator進行參數(shù)校驗最佳實踐記錄

    SpringMVC使用hibernate-validator進行參數(shù)校驗最佳實踐記錄

    這篇文章主要介紹了SpringMVC使用hibernate-validator進行參數(shù)校驗最佳實踐,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-05-05
  • HashSet和TreeSet使用方法的區(qū)別解析

    HashSet和TreeSet使用方法的區(qū)別解析

    這篇文章主要介紹了HashSet和TreeSet使用方法的區(qū)別解析,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Mybatis實現(xiàn)Mapper動態(tài)代理方式詳解

    Mybatis實現(xiàn)Mapper動態(tài)代理方式詳解

    這篇文章主要為大家詳細介紹了Mybatis實現(xiàn)Mapper動態(tài)代理方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • 最新log4j2遠程代碼執(zhí)行漏洞(附解決方法)

    最新log4j2遠程代碼執(zhí)行漏洞(附解決方法)

    Apache?Log4j2?遠程代碼執(zhí)行漏洞攻擊代碼,該漏洞利用無需特殊配置,經(jīng)多方驗證,Apache?Struts2、Apache?Solr、Apache?Druid、Apache?Flink等均受影響,本文就介紹一下解決方法
    2021-12-12

最新評論

紫金县| 天峻县| 霸州市| 石渠县| 扬州市| 普定县| 恭城| 湘潭市| 红桥区| 汾西县| 日照市| 金溪县| 平南县| 遂平县| 湛江市| 星子县| 青州市| 阿瓦提县| 腾冲县| 安龙县| 靖远县| 西宁市| 麻江县| 莆田市| 新竹县| 佛坪县| 沅江市| 深州市| 连平县| 垣曲县| 天柱县| 满城县| 谷城县| 山阴县| 叙永县| 公主岭市| 玉田县| 贺州市| 隆尧县| 启东市| 平南县|