詳解spring-boot下如何滿足多生產(chǎn)環(huán)境中個(gè)性化定制功能
在項(xiàng)目的開發(fā)中,我們很難做到開發(fā)一套標(biāo)準(zhǔn)的流程來解決所有客戶的需求。比如,我們當(dāng)前的計(jì)量項(xiàng)目,分別運(yùn)行于赤峰市和河北省。雖然兩個(gè)區(qū)域處理的業(yè)務(wù)相同,但是對細(xì)節(jié)的實(shí)現(xiàn)要求卻不同。前面也學(xué)習(xí)過計(jì)量檢定軟件,其為了解決各個(gè)定制者使用的功能需求,最后采取的方案是:將基礎(chǔ)項(xiàng)目復(fù)制多份,進(jìn)而滿足不同的客戶需求。優(yōu)點(diǎn)當(dāng)然是有的,但比起缺點(diǎn)來,優(yōu)點(diǎn)便不值一提。缺點(diǎn)很明顯,總結(jié)為一句話就是:項(xiàng)目變得難以維護(hù)。所以,當(dāng)前讓我們看到的就是,幾個(gè)開發(fā)人員,每天處于解決問題當(dāng)中。本文將給出一種方案,來有效的規(guī)避上述問題。
資源與環(huán)境
示例代碼:https://github.com/mengyunzhi/springBootSampleCode/tree/master/dynamic-autowire
開發(fā)環(huán)境:java1.8 + spring-boot:2.1.3.RELEASE
需求假設(shè)
- 假設(shè)使用本項(xiàng)目的人員為:中國人、美國人,分別能接受的語言為中文和英文。
- 項(xiàng)目運(yùn)行后,可以根據(jù)當(dāng)前的訪問人員是國籍來動態(tài)顯示:
你好
或hello
- 有新的需求后,比如:增加德國人并顯示
Hallo
。增加功能時(shí),不更改核心代碼。 - 不使用if else
注意:如果你看完需求假設(shè)后,毫無觸動,請忽略本文以下內(nèi)容
解決方案
解決方案中,我們涉及了兩種設(shè)計(jì)模塊,分別為:策略模式
及工廠模式
。
策略模式:一般用于將具體的算法
進(jìn)行抽象及剝離。此項(xiàng)目中,我們的具體算法是說你好
。
工廠模式:一般用于根據(jù)環(huán)境來動態(tài)的創(chuàng)建BEAN的情況下。引項(xiàng)目中,我們將根據(jù)不同國家的人,來返回不同的說你好
這個(gè)算法。
先給出UML圖:
SpeakService
SpeakService
即為我們供其它模塊調(diào)用的說話服務(wù)
,調(diào)用其中的SayHello()
來完成說你好
功能。
package com.mengyunzhi.demo.dynamicautowire; /** * 你好 */ public interface SpeakService { void sayHello(); }
在其實(shí)現(xiàn)類中,我們注入SayHelloFactory
,讓其來返回正確的SayHelloService
,最終調(diào)用sayHello()
來完成目標(biāo)。
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * 你好 */ @Service public class SpeakServiceImpl implements SpeakService { private final SayHelloFactory sayHelloFactory; // 說話工廠 @Autowired public SpeakServiceImpl(SayHelloFactory sayHelloFactory) { this.sayHelloFactory = sayHelloFactory; } @Override public void sayHello() { this.sayHelloFactory.getSayHelloService().sayHello(); } }
SayHelloFactory
package com.mengyunzhi.demo.dynamicautowire; /** * 說話工廠 */ public interface SayHelloFactory { void setCountryCode(CountryCode countryCode); SayHelloService getSayHelloService(); }
在此,我們增加一個(gè)CountryCode
表示當(dāng)前訪問者的國家。其實(shí)在獲取訪問者國家時(shí),我們也可以調(diào)用其它Bean的其它來實(shí)現(xiàn)。
package com.mengyunzhi.demo.dynamicautowire; /** * 國家代碼 */ public enum CountryCode { CHINA((byte) 0, "中國"), USA((byte) 1, "美國"); private Byte code; private String name; CountryCode(Byte code, String name) { this.code = code; this.name = name; } public Byte getCode() { return code; } public String getName() { return name; } }
使用enum
來控制范圍,避免Factory
在獲取Bean時(shí)發(fā)生異常。
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 說話工廠 */ @Service public class SayHelloFactoryImpl implements SayHelloFactory { /** * BEAN列表 */ private final Map<Byte, SayHelloService> servicesByCode = new HashMap<>(); /** * 國家代碼 */ private CountryCode countryCode = CountryCode.CHINA; @Override public void setCountryCode(CountryCode countryCode) { this.countryCode = countryCode; } /** * 初始化 * * @param sayHelloServices spring獲取到的所以實(shí)現(xiàn)了SpeakService的BEAN */ @Autowired public void init(List<SayHelloService> sayHelloServices) { for (SayHelloService sayHelloService : sayHelloServices) { this.register(sayHelloService.getCode(), sayHelloService); } } /** * 注冊Bean * * @param code 代碼 * @param sayHelloService BEAN */ private void register(Byte code, SayHelloService sayHelloService) { this.servicesByCode.put(code, sayHelloService); } /** * 獲取BEAN * * @return 對應(yīng)的SayHelloService BEAN */ @Override public SayHelloService getSayHelloService() { return this.servicesByCode.get(this.countryCode.getCode()); } }
增加Map<Byte, SayHelloService> servicesByCode
來存儲對應(yīng)國家的SayHelloService
BEAN。增加getSayHelloService()
來根據(jù)當(dāng)前國家代碼來返回相應(yīng)的Bean。
SayHelloService
package com.mengyunzhi.demo.dynamicautowire; /** * 說話 */ public interface SayHelloService { void sayHello(); Byte getCode(); }
將sayHello()
方法抽離,getCode()
以獲取國家代碼。
中國人你好
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.Component; /** * 中國話 */ @Component public class SayHelloServiceChineseImpl implements SayHelloService { @Override public void sayHello() { System.out.println("您好"); } @Override public Byte getCode() { return CountryCode.CHINA.getCode(); } }
美國人Hello
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.Component; /** * 美國話 */ @Component public class SayHelloServiceEnglishImpl implements SayHelloService { @Override public void sayHello() { System.out.println("hello"); } @Override public Byte getCode() { return CountryCode.USA.getCode(); } }
測試
package com.mengyunzhi.demo.dynamicautowire; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest @RunWith(SpringRunner.class) public class SpeakServiceImplTest { @Autowired SpeakService speakService; @Autowired SayHelloFactory sayHelloFactory; @Test public void sayHello() { // 默認(rèn)說你好 speakService.sayHello(); // 將國家設(shè)置為美國,再說你好 sayHelloFactory.setCountryCode(CountryCode.USA); speakService.sayHello(); // 將國家設(shè)置為中國,再說你好 sayHelloFactory.setCountryCode(CountryCode.CHINA); speakService.sayHello(); } }
您好
hello
您好
時(shí)序圖
增加德國人
增加德國人SayHelloServiceGermanyImpl
.
在CountryCode
中,增加德國.
package com.mengyunzhi.demo.dynamicautowire; import org.springframework.stereotype.Component; @Component public class SayHelloServiceGermanyImpl implements SayHelloService { @Override public void sayHello() { System.out.println("Hallo"); } @Override public Byte getCode() { return CountryCode.GERMANY.getCode(); } }
package com.mengyunzhi.demo.dynamicautowire; /** * 國家代碼 */ public enum CountryCode { CHINA((byte) 0, "中國"), USA((byte) 1, "美國"), GERMANY((byte) 2, "德國"); private Byte code; private String name; CountryCode(Byte code, String name) { this.code = code; this.name = name; } public Byte getCode() { return code; } public String getName() { return name; } }
單元測試
@Test public void sayHello1() { // 默認(rèn)說你好 speakService.sayHello(); // 將國家設(shè)置為美國,再說你好 sayHelloFactory.setCountryCode(CountryCode.USA); speakService.sayHello(); // 將國家設(shè)置為德國,再說你好 sayHelloFactory.setCountryCode(CountryCode.GERMANY); speakService.sayHello(); // 將國家設(shè)置為中國,再說你好 sayHelloFactory.setCountryCode(CountryCode.CHINA); speakService.sayHello(); }
測試結(jié)果如下:
您好
hello
Hallo
您好
總結(jié)
在解決問題時(shí),只所有我們看的不夠遠(yuǎn),可能是由于自己站的不夠高。同樣的問題,困惑我了多日,直到近期系統(tǒng)的學(xué)習(xí)設(shè)計(jì)模式
、angular官方教程
、Spring 實(shí)戰(zhàn)
后,結(jié)合近期項(xiàng)目變更帶來的新需求,才在使用設(shè)計(jì)模式解決此問題上有所啟發(fā)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- spring中通過ApplicationContext getBean獲取注入對象的方法實(shí)例
- Springboot-dubbo-fescar 阿里分布式事務(wù)的實(shí)現(xiàn)方法
- Spring 中優(yōu)雅的獲取泛型信息的方法
- spring @Transactional 無效的解決方案
- spring boot定時(shí)任務(wù)接收郵件并且存儲附件的方法講解
- activemq整合springboot使用方法(個(gè)人微信小程序用)
- Springboot項(xiàng)目打war包docker包找不到resource下靜態(tài)資源的解決方案
- Spring自帶的校驗(yàn)框架Validation的使用實(shí)例
- 詳解Spring框架下向異步線程傳遞HttpServletRequest參數(shù)的坑
- Spring通過ApplicationContext主動獲取bean的方法講解
相關(guān)文章
Spring之動態(tài)注冊bean的實(shí)現(xiàn)方法
這篇文章主要介紹了Spring之動態(tài)注冊bean的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08java堆棧類使用實(shí)例(java中stack的使用方法)
java中stack的使用方法,堆棧是一種"后進(jìn)先出"(LIFO) 的數(shù)據(jù)結(jié)構(gòu), 只能在一端進(jìn)行插入(稱為"壓棧") 或刪除 (稱為"出棧")數(shù)據(jù)的操作,下面看示例吧2013-12-12關(guān)于IDEA使用jsp可以訪問頁面轉(zhuǎn)換為html彈出頁面為404的問題
這篇文章主要介紹了關(guān)于IDEA使用jsp可以訪問頁面轉(zhuǎn)換為html彈出頁面為404的問題及解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12Java 客戶端操作 FastDFS 實(shí)現(xiàn)文件上傳下載替換刪除功能
這篇文章主要介紹了Java 客戶端操作 FastDFS 實(shí)現(xiàn)文件上傳下載替換刪除功能,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10Java虛擬機(jī)內(nèi)存結(jié)構(gòu)及編碼實(shí)戰(zhàn)分享
這篇文章主要介紹了Java虛擬機(jī)內(nèi)存結(jié)構(gòu)及編碼實(shí)戰(zhàn)分享,文章圍繞詳細(xì)主題展開相關(guān)資料具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-04-04Jpa 實(shí)現(xiàn)自動更新表中的創(chuàng)建日期和修改時(shí)間
這篇文章主要介紹了Jpa 實(shí)現(xiàn)自動更新表中的創(chuàng)建日期和修改時(shí)間,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01