男的直接做的視頻網(wǎng)站站長seo推廣
目錄
前言
UML
plantuml
類圖
實戰(zhàn)代碼
AbstractRoutingDataSource
DynamicDataSource
DynamicDataSourceContextHolder
前言
在設(shè)計類時,一般優(yōu)先考慮使用組合來替代繼承,能夠讓程序更加的靈活,但這并不意味著要完全拋棄掉繼承。
繼承在面向?qū)ο缶幊讨杏脕頊p少代碼冗余和提高復(fù)用性,是面向?qū)ο缶幊痰囊淮筇匦浴?/p>
只不過在使用繼承時必須滿足一些條件,才能讓我們更好地利用繼承,設(shè)計出更易維護和擴展的程序。
一般情況下,使用繼承需要滿足一下兩個條件
- 父類所有的屬性和方法,都能在子類中適用
- 子類無需復(fù)用其他類的方法,并且不會覆寫父類已有的方法
模板方法模式是繼承使用的優(yōu)雅示例,一般會設(shè)計一個抽象類,在類中定義了一個操作的算法結(jié)構(gòu),其中一些步驟被設(shè)計為抽象方法,需要子類去實現(xiàn),這些方法被稱為模板方法。
模板方法允許子類在不改變算法結(jié)構(gòu)的情況下,重新定義算法的某些特定步驟。
UML
plantuml
@startuml 'https://plantuml.com/class-diagramabstract Template {+ doSomething() : void- step1() : void- step2() : void+ {abstract} step3() : void }class Concrete {+ step3() : void }class Client {}Template <|-- ConcreteClient ..> Concrete @enduml
類圖
實戰(zhàn)代碼
AbstractRoutingDataSource
業(yè)務(wù)上需要用到動態(tài)數(shù)據(jù)源,可以繼承?spring 框架提供的抽象類?AbstractRoutingDataSource 來實現(xiàn)運行中動態(tài)切換數(shù)據(jù)源功能。
初始化動態(tài)數(shù)據(jù)源時,將所有的數(shù)據(jù)源都保存在?private Map<Object, DataSource> resolvedDataSources 中,每一個數(shù)據(jù)源對應(yīng)一個唯一標(biāo)識。
抽象類定義了決定目標(biāo)數(shù)據(jù)源的方法(determineTargetDataSource),用來決定當(dāng)前操作要使用動態(tài)數(shù)據(jù)源中的哪一個數(shù)據(jù)源,方法中調(diào)用了模板方法(determineCurrentLookupKey),子類只需要實現(xiàn)?determineCurrentLookupKey 這個模板方法,動態(tài)地返回數(shù)據(jù)源唯一標(biāo)識,便能夠?qū)崿F(xiàn)動態(tài)切換數(shù)據(jù)源了
determineTargetDataSource 與?determineCurrentLookupKey
DynamicDataSource
public class DynamicDataSource extends AbstractRoutingDataSource {public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {super.setDefaultTargetDataSource(defaultTargetDataSource);super.setTargetDataSources(targetDataSources);super.afterPropertiesSet();}@Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceContextHolder.getDataSourceType();}
}
DynamicDataSourceContextHolder
public class DynamicDataSourceContextHolder {/*** 使用ThreadLocal維護變量,ThreadLocal為每個使用該變量的線程提供獨立的變量副本,* 所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應(yīng)的副本。*/private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();/*** 設(shè)置數(shù)據(jù)源變量* @param dataSourceType*/public static void setDataSourceType(String dataSourceType){System.out.printf("切換到{%s}數(shù)據(jù)源", dataSourceType);CONTEXT_HOLDER.set(dataSourceType);}/*** 獲取數(shù)據(jù)源變量* @return*/public static String getDataSourceType(){return CONTEXT_HOLDER.get();}/*** 清空數(shù)據(jù)源變量*/public static void clearDataSourceType(){CONTEXT_HOLDER.remove();}
}