枚舉的高階用法之枚舉里寫方法以及注入spring的bean

1、前言

??一般我們使用枚舉都是用來定義一些常量。比如我們需要一個表示訂單類(pc訂單、手機訂單)的常量,那我們就可以使用枚舉來實現,如下:

@AllArgsConstructor
public enum OrderTypeEnum{PC("PC", "電腦端"),PHONE("PHONE", "手機端");private String name;private String value;}

??接著再寫一下根據name查找對應枚舉的方法,枚舉就算完成了。但比如我們的業務場景是這樣的:我們有一個OrderTypeService接口及其實現類。

public interface OrderTypeService {String processPc(String order);String processPhone(String order);
}
@Service
public class OrderTypeServiceImpl implements OrderTypeService {@Overridepublic String processPc(String order) {//具體的處理pc訂單的業務邏輯System.out.println("開始處理pc訂單:" + order);return null;}@Overridepublic String processPhone(String order) {//具體的處理phone訂單的業務邏輯System.out.println("開始處理phone訂單:" + order);return null;}
}

??根據接口的方法名我們一眼就知道,processPc是用來處理PC訂單的;processPhone是用來處理PHONE訂單的。然后再實際調用這兩個方法的地方就需要我們進行if-else的判斷。這里的if-else判斷的缺點是:代碼擴展性很差,如果以后又增加了其它訂單類型,我們還需要改這里的if-else邏輯。

        if (OrderTypeEnum.PC.equals(orderTypeEnum)) {orderTypeService.processPc("order");} else if (OrderTypeEnum.PHONE.equals(orderTypeEnum)) {orderTypeService.processPhone("order");}

2、思考

??針對以上if-else判斷存在的問題,那我們能不能把調用各自業務邏輯的代碼挪到枚舉里呢?肯定是可以的,本期我們就來實現一下。

2.1、通過@PostConstruct注解

在枚舉內定義BeanInjector,再通過PostConstruct注解的方法給枚舉的orderTypeService屬性注入bean。

@AllArgsConstructor
public enum OrderTypeEnum {PC("PC", "電腦端") {@Overridepublic void handle(String order) {orderTypeService.processPc(order);}},PHONE("PHONE", "手機端") {@Overridepublic void handle(String order) {orderTypeService.processPhone(order);}};private String name;private String value;protected static OrderTypeService orderTypeService;public abstract void handle(String order);@Componentpublic static class BeanInjector {@Autowiredprivate OrderTypeService orderTypeService;@PostConstructpublic void postConstruct() {OrderTypeEnum.orderTypeService = this.orderTypeService;}}
}

調用代碼:

        OrderTypeEnum pcOrderType = OrderTypeEnum.PC;pcOrderType.handle("1");

輸出結果:

開始處理pc訂單:1

2.2、在枚舉內實現ApplicationContextAware回調接口,獲取到ApplicationContext,再從context里獲取我們需要的bean

@AllArgsConstructor
public enum OrderTypeEnum {PC("PC", "電腦端") {@Overridepublic void handle(String order) {OrderTypeService orderTypeService = OrderTypeEnum.ApplicationContextProvider.getApplicationContext().getBean(OrderTypeService.class);orderTypeService.processPc(order);}},PHONE("PHONE", "手機端") {@Overridepublic void handle(String order) {OrderTypeService orderTypeService = OrderTypeEnum.ApplicationContextProvider.getApplicationContext().getBean(OrderTypeService.class);orderTypeService.processPhone(order);}};private String name;private String value;public abstract void handle(String order);@Componentpublic static class ApplicationContextProvider implements ApplicationContextAware {private static ApplicationContext context;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {context = applicationContext;}public static ApplicationContext getApplicationContext() {return context;}}
}

調用代碼同2.1
輸出結果同2.1

2.3、還是需要實現ApplicationContextAware接口,但這次不是直接使用ApplicationContext,而是把ApplicationContext里的bean值直接注入到我們的枚舉字段中。

public enum OrderTypeEnum {PC("PC", "電腦端") {@Overridepublic void handle(String order) {orderTypeService.processPc(order);}},PHONE("PHONE", "手機端") {@Overridepublic void handle(String order) {orderTypeService.processPhone(order);}};private String name;private String value;OrderTypeEnum(String name, String value) {this.name = name;this.value = value;}public abstract void handle(String order);@AutowiredOrderTypeService orderTypeService;
}
@Component
public class OrderTypeEnumInjector implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {for (OrderTypeEnum orderTypeEnum : OrderTypeEnum.values()) {applicationContext.getAutowireCapableBeanFactory().autowireBean(orderTypeEnum);}}
}

調用代碼同2.1
輸出結果同2.1
??這里重點是使用applicationContext.getAutowireCapableBeanFactory().autowireBean。它可以把枚舉中使用了@Autowired注解的字段和applicationContext中的bean根據類型和名稱做匹配,匹配到之后就會把bean注入到該字段中。從而枚舉中的orderTypeService就有值了。

3、延申

??applicationContext.getAutowireCapableBeanFactory().autowireBean能否給普通的類(沒有被spring管理)的字段注入bean呢?答案也是可以的,這里最好把這個普通對象定義成單例的,這樣我們給字段注入一次bean就可以一直使用了,否則每次new 的時候還需要重新注入bean。

public class OrderTypeManager {private OrderTypeManager(){}private static OrderTypeManager orderTypeManager = null;public synchronized static OrderTypeManager getInstance(){if(orderTypeManager == null){orderTypeManager = new OrderTypeManager();}return orderTypeManager;}@Autowiredprivate OrderTypeService orderTypeService;public  void test(){orderTypeService.processPhone("2");}
}

??如上定義了一個單例的OrderTypeManager,但是OrderTypeManager沒有被spring所管理,那我們怎么把OrderTypeService這個bean注入到orderTypeService字段里呢?

@Component
public class OrderTypeEnumInjector implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {for (OrderTypeEnum orderTypeEnum : OrderTypeEnum.values()) {applicationContext.getAutowireCapableBeanFactory().autowireBean(orderTypeEnum);}OrderTypeManager orderTypeManager = OrderTypeManager.getInstance();applicationContext.getAutowireCapableBeanFactory().autowireBean(orderTypeManager);}
}

調用代碼:

        OrderTypeManager orderTypeManager = OrderTypeManager.getInstance();orderTypeManager.test();

輸出結果:

開始處理phone訂單:2

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45255.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45255.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45255.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[計網初識2]web的3個核心標準html,url,http

學習內容 HTML,URL,HTTP的構成 1.規范web的3個核心標準? HTML(Hyper Text Markup Language),規范網頁內容和版面布局的表示標準。URL(Uniform Resource Locator),規范網頁識別符格式和含義的表示標準。HTTP(HyperText Transfer Protocl),規范游覽器如…

JIRA的高級搜索JIRA Query Language(JQL)詳解

JIRA的高級搜索功能非常強大,允許用戶通過JIRA Query Language(JQL)來構建復雜的查詢。以下是一些常用的高級搜索用法和示例: 1. 基本語法 JQL的基本語法包括字段、運算符和值的組合。例如: field operator value2.…

<數據集>UA-DETRAC車輛識別數據集<目標檢測>

數據集格式:VOCYOLO格式 圖片數量:20500張 標注數量(xml文件個數):20500 標注數量(txt文件個數):20500 標注類別數:4 標注類別名稱:[car, van, others, bus] 序號類別名稱圖片數框數1car201871259342…

鋇錸ARMxy控制器在智能網關中的應用

隨著IoT物聯網技術的飛速發展,智能網關作為連接感知層與網絡層的樞紐,可以實現感知網絡和通信網絡以及不同類型感知網絡之間的協議轉換。鋇錸技術的ARMxy系列控制器憑借其高性能、低功耗和高度靈活性的特點,在智能網關中發揮了關鍵作用&#…

數據結構回顧(Java)

1.數組 線性表 定義的方式 int[] anew int[10] 為什么查詢快? 1.可以借助O(1)時間復雜度訪問某一元素, 2.地址連續,邏輯連續 3.數組長度一旦確定就不可以被修改 當需要擴容的時候需要將老數組的內容復制過來 在Java中數組是一個對象 Ar…

bug定位策略

前提--用戶環境層面 hosts異常:hosts文件主要是加快某個域名或者網站的解析速度,從而達到快速訪問的作用,也可以屏蔽網站。hosts異常可能會導致部分網頁無法訪問,能夠加載,但是網頁無法正常顯示;測試環境臟…

記錄些Redis題集(2)

Redis 的多路IO復用 多路I/O復用是一種同時監聽多個文件描述符(如Socket)的狀態變化,并能在某個文件描述符就緒時執行相應操作的技術。在Redis中,多路I/O復用技術主要用于處理客戶端的連接請求和讀寫操作,以實現高并發…

Python_使用pyecharts構建折線圖

Pyecharts簡介 Pyecharts是一款將python與echarts結合的強大的數據可視化工具,使用 pyecharts 可以生成獨立的網頁,也可以在 flask , Django 中集成使用。echarts :百度開源的一個數據可視化 JS 庫,主要用于數據可視化。pyechart…

嵌入式linux相機 框圖

攝像頭讀取數據顯示到LCD流程 重點:攝像頭數據(yuyv,mjpeg,rgb)(640,320)與LCD顯示數據(RGB)(480,240)不同;需要轉換&…

ReactRouter v6升級的步驟

React Router v6 引入了一個 Routes 組件&#xff0c;它有點像 Switch &#xff0c;但功能要強大得多。與 Switch 相比&#xff0c; Routes 的主要優勢在于&#xff1a; <Routes> 中的所有 <Route> 和 <Link> 都是相對的。這導致在 <Route path> 和 &…

項目文章|EMBO J(IF=9.4):16S+代謝組解析腸道菌群代謝物改善高脂飲食誘導的胰島素抵抗機制

腸道菌群及其代謝產物與肥胖相關疾病&#xff08;如2型糖尿病&#xff09;密切相關&#xff0c;但其因果關系和潛在機制尚不清楚。研究表明&#xff0c;肥胖與腸道微生物的豐度和多樣性變化有關&#xff0c;例如&#xff0c;高脂飲食&#xff08;HFD&#xff09;誘導的肥胖會增…

AIGC率超標?掌握論文去AI痕跡的高效策略

隨著 AI 技術迅猛發展&#xff0c;各種AI輔助論文寫作的工具層出不窮&#xff01; 為了防止有人利用AI工具進行論文代寫&#xff0c;在最新的學位法中已經明確規定“已經獲得學位者&#xff0c;在獲得該學位過程中如有人工智能代寫等學術不端行為&#xff0c;經學位評定委員會…

ESP32CAM物聯網教學11

ESP32CAM物聯網教學11 霍霍webserver 在第八課的時候&#xff0c;小智把樂鑫公司提供的官方示例程序CameraWebServer改成了明碼&#xff0c;這樣說明這個官方程序也是可以更改的嘛。這個官方程序有四個文件&#xff0c;一共3500行代碼&#xff0c;看著都頭暈&#xff0c;小智決…

S7-200smart與C#通信

https://www.cnblogs.com/heizao/p/15797382.html C#與PLC通信開發之西門子s7-200 smart_c# s7-200smart通訊庫-CSDN博客https://blog.csdn.net/weixin_44455060/article/details/109713121 C#上位機讀寫西門子S7-200SMART PLC變量 教程_嗶哩嗶哩_bilibilihttps://www.bilibili…

清朝嘉慶二十五年(1820年)地圖數據

我們在《中國歷史行政區劃連續變化數據》一文中&#xff0c;為你分享了中國歷史行政區劃連續變化地圖數據。 現在再為你分享清朝嘉慶二十五年&#xff08;1820年&#xff09;的地圖數據&#xff0c;該數據對于研究歷史的朋友應該比較有用&#xff0c;請在文末查看領取方式。 …

【Rust練習】2.數值類型

練習題來自https://practice-zh.course.rs/basic-types/numbers.html 1 // 移除某個部分讓代碼工作 fn main() {let x: i32 5;let mut y: u32 5;y x;let z 10; // 這里 z 的類型是? }y的類型不對&#xff0c;另外&#xff0c;數字的默認類型是i32 fn main() {let x: i…

Jupyter Lab 使用

Jupyter Lab 使用詳解 Jupyter Lab 是一個基于 Web 的交互式開發環境&#xff0c;提供了比 Jupyter Notebook 更加靈活和強大的用戶界面和功能。以下是使用 Jupyter Lab 的詳細指南&#xff0c;包括安裝、基本使用、設置根目錄和擴展功能等內容。 一、Jupyter Lab 安裝與啟動…

HTTP背后的故事:理解現代網絡如何工作的關鍵(一)

一.HTTP是什么 概念 &#xff1a; 1.HTTP ( 全稱為 " 超文本傳輸協議 ") 是一種應用非常廣泛的 應用層協議。 2.HTTP 誕生與1991年. 目前已經發展為最主流使用的一種應用層協議. 3.HTTP 往往是基于傳輸層的 TCP 協議實現的 . (HTTP1.0, HTTP1.1, HTTP2.0 均為 T…

DelphiXE內存泄漏問題,已經發生了很多次

內存泄漏的地方一定要注意: 不斷分配的Tbytes會導致內存泄漏,發生以下錯誤: Access violation at address CA5ED400. Execution of address CA5ED400 {=====內存泄漏最大的地方、居然沒有釋放=====} //SetLength(tbuff,length(Adata)); //Move(Adata,Tbuff,length(…

2024世界人工智能大會(WAIC)學習總結

1 前言 在2024年的世界人工智能大會&#xff08;WAIC&#xff09;上&#xff0c;我們見證了從農業社會到工業社會再到數字化社會的深刻轉變。這一進程不僅體現在技術的單點爆發&#xff0c;更引發了整個產業鏈的全面突破&#xff0c;未來將是技術以指數級速度發展的嶄新時代。…