Spring中的策略模式簡(jiǎn)單實(shí)現(xiàn)與使用分析
一、策略模式
策略模式的網(wǎng)上一搜索就會(huì)出現(xiàn)很多的說(shuō)明,并且大多數(shù)的例子基本都來(lái)自《Head First設(shè)計(jì)模式》《大話設(shè)計(jì)模式》等,并且過(guò)于文字化的介紹總是讓本來(lái)簡(jiǎn)單的事情更加復(fù)雜化。
所以還是直接上demo,方便理解。Head First上的策略模式例子稍微復(fù)雜一些,代碼比較多就不進(jìn)行展示了
這里可以寫(xiě)一個(gè)最簡(jiǎn)單的策略模式,也可以理解為Java多態(tài)。
1、 創(chuàng)建一個(gè)策略抽象
public abstract class AbstractStrategy { /** * 抽象的策略接口 */ abstract void algorithm(); }
2、策略的N中實(shí)現(xiàn)
public class StrategyImplOne extends AbstractStrategy { @Override void algorithm() { System.out.println("我實(shí)現(xiàn)了策略(一)的方法?。?!"); } }
public class StrategyImplTwo extends AbstractStrategy { @Override void algorithm() { System.out.println("我實(shí)現(xiàn)了策略(二)的方法?。。?); } }
3、為策略的調(diào)用創(chuàng)建一個(gè)觸發(fā)容器(方法調(diào)用觸發(fā))
public class Context { private AbstractStrategy strategy; public Context(AbstractStrategy strategy) { this.strategy = strategy; } /** * 觸發(fā)策略執(zhí)行 */ public void strategyImpl() { strategy.algorithm(); } }
4、測(cè)試簡(jiǎn)單的策略模式
public class StrategyTest { public static void main(String[] args) { // 執(zhí)行策略一 new Context(new StrategyImplOne()).strategyImpl(); // 執(zhí)行策略二 new Context(new StrategyImplTwo()).strategyImpl(); } }
5、查看結(jié)果
我實(shí)現(xiàn)了策略(一)的方法?。?!
我實(shí)現(xiàn)了策略(二)的方法?。?!
二、Spring中的策略模式
當(dāng)我們看完上一個(gè)策略模式的demo的時(shí)候發(fā)現(xiàn)并沒(méi)有什么用,或者我不知道自己在項(xiàng)目里面怎么進(jìn)行使用,所以可以看看別人的框架是怎么使用的,或者說(shuō)看看好的源碼中是怎么使用的。
1、Spring MVC中 DispatcherServlet 使用策略模式
DispatcherServlet在進(jìn)行轉(zhuǎn)發(fā)前需要進(jìn)行傳說(shuō)中的九大件的初始化,其中去初始化時(shí)除了initMultipartResolver(上傳文件)沒(méi)有獲取Properties defaultStrategies;默認(rèn)策略,其他的八大件都會(huì)使用到策略模式。
先看一下defaultStrategies為 java.util.Properties類型,定義如下:
public class Properties extends Hashtable<Object, Object> { // *** }
流程梳理:
1、當(dāng)Web容器啟動(dòng)時(shí),ServletWebServerApplicationContext初始化會(huì)調(diào)用其refresh()方法,則會(huì)調(diào)用 DispatcherServlet的onRefresh方法
2、onRefresh方法 - >initStrategies方法 -> 初始化九大件
3、初始化時(shí)則會(huì)調(diào)用getDefaultStrategy方法。如下:
4、getDefaultStrategy實(shí)現(xiàn),就是去調(diào)用了Properties這個(gè)Hashtable的key對(duì)應(yīng)的value值,如下:
protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) { List<T> strategies = this.getDefaultStrategies(context, strategyInterface); if (strategies.size() != 1) { throw new BeanInitializationException("DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]"); } else { return strategies.get(0); } }
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) { String key = strategyInterface.getName(); String value = defaultStrategies.getProperty(key); if (value == null) { return new LinkedList(); } else { String[] classNames = StringUtils.commaDelimitedListToStringArray(value); List<T> strategies = new ArrayList(classNames.length); String[] var7 = classNames; int var8 = classNames.length; for(int var9 = 0; var9 < var8; ++var9) { String className = var7[var9]; try { Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader()); Object strategy = this.createDefaultStrategy(context, clazz); strategies.add(strategy); } catch (ClassNotFoundException var13) { throw new BeanInitializationException("Could not find DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var13); } catch (LinkageError var14) { throw new BeanInitializationException("Unresolvable class definition for DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var14); } } return strategies; } }
5、那么Properties的值在哪里添加進(jìn)去的呢,DispatcherServlet 的static靜態(tài)代碼塊中會(huì)看見(jiàn),是用Spring的Resource將配置文件中的配置加載,設(shè)置到這個(gè)Map容器中的,如下:
static { try { ClassPathResource resource = new ClassPathResource("DispatcherServlet.properties", DispatcherServlet.class); defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } catch (IOException var1) { throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + var1.getMessage()); } }
6、在看看 DispatcherServlet.properties 配置就明白了,就是九大件沒(méi)傳時(shí)的默認(rèn)值,其實(shí)也可以考慮用SPI機(jī)制實(shí)現(xiàn)(記得之前好像是不是有版本就是用SPI實(shí)現(xiàn)的)。
# Default implementation classes for DispatcherServlet's strategy interfaces. # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
總結(jié)
web容器啟動(dòng),ServletWebServerApplicationContext的refresh方法間接調(diào)用到 DispatcherServlet的初始九大件方法, 其中八大件在沒(méi)有自定義實(shí)現(xiàn)的情況下,調(diào)用默認(rèn)的 配置。
而默認(rèn)配置則是在 DispatcherServlet的靜態(tài)代碼塊中,由Spring的ClassPathResource將配置文件DispatcherServlet.properties中的配置加載進(jìn)一個(gè) Map容器中。
只待初始化九大件時(shí),根據(jù)不同的九大件類型作為key,調(diào)用相應(yīng)的實(shí)現(xiàn)。
到此這篇關(guān)于Spring中的策略模式簡(jiǎn)單實(shí)現(xiàn)與使用分析的文章就介紹到這了,更多相關(guān)Spring策略模式簡(jiǎn)單實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringSecurity OAtu2+JWT實(shí)現(xiàn)微服務(wù)版本的單點(diǎn)登錄的示例
本文主要介紹了SpringSecurity OAtu2+JWT實(shí)現(xiàn)微服務(wù)版本的單點(diǎn)登錄的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05java并發(fā)編程專題(六)----淺析(JUC)Semaphore
這篇文章主要介紹了java JUC)Semaphore的相關(guān)資料,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07Spring?myBatis數(shù)據(jù)庫(kù)連接異常問(wèn)題及解決
這篇文章主要介紹了Spring?myBatis數(shù)據(jù)庫(kù)連接異常問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06學(xué)習(xí)Java之如何正確地跳出循環(huán)結(jié)構(gòu)
我們?cè)诶醚h(huán)執(zhí)行重復(fù)操作的過(guò)程中,存在著一個(gè)需求:如何中止,或者說(shuō)提前結(jié)束一個(gè)循環(huán),所以就給大家講解一下,如何在java代碼中返回一個(gè)結(jié)果,如何結(jié)束和跳出一個(gè)循環(huán),需要的朋友可以參考下2023-05-05Maven的使用和配置國(guó)內(nèi)源的保姆級(jí)教程
Maven是?個(gè)項(xiàng)目管理工具,基于POM(Project Object Model,項(xiàng)目對(duì)象模型)的概念,Maven可以通過(guò)一小段描述信息來(lái)管理項(xiàng)目的構(gòu)建,報(bào)告和文檔的項(xiàng)目管理工具軟件,很多新手還不夠了解maven,所以本文給大家講解Maven的使用和配置,需要的朋友可以參考下2025-04-04java.lang.Runtime.exec() Payload知識(shí)點(diǎn)詳解
在本篇文章里小編給大家整理的是一篇關(guān)于java.lang.Runtime.exec() Payload知識(shí)點(diǎn)相關(guān)內(nèi)容,有興趣的朋友們學(xué)習(xí)下。2020-03-03