日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot解耦的扩展机制 Spring Factories介绍及使用

發布時間:2025/3/15 javascript 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot解耦的扩展机制 Spring Factories介绍及使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、什么是 SPI機制

Spring Boot中有一種非常解耦的擴展機制:Spring Factories。這種擴展機制實際上是仿照Java中的SPI擴展機制來實現的。SPI的全名為Service Provider Interface.大多數開發人員可能不熟悉,因為這個是針對廠商或者插件的。在java.util.ServiceLoader的文檔里有比較詳細的介紹。簡單的總結下java SPI機制的思想。我們系統里抽象的各個模塊,往往有很多不同的實現方案,比如日志模塊的方案,xml解析模塊、jdbc模塊的方案等。面向的對象的設計里,我們一般推薦模塊之間基于接口編程,模塊之間不對實現類進行硬編碼。一旦代碼里涉及具體的實現類,就違反了可拔插的原則,如果需要替換一種實現,就需要修改代碼。為了實現在模塊裝配的時候能不在程序里動態指明,這就需要一種服務發現機制。java SPI就是提供這樣的一個機制:為某個接口尋找服務實現的機制。有點類似IOC的思想,就是將裝配的控制權移到程序之外,在模塊化設計中這個機制尤其重要。

二、Spring Boot中的SPI機制

在Spring中也有一種類似與Java SPI的加載機制。它在META-INF/spring.factories文件中配置接口的實現類名稱,然后在程序中讀取這些配置文件并實例化。這種自定義的SPI機制是Spring Boot Starter實現的基礎。


spring.factories

三、Spring Factories實現原理

spring-core包里定義了SpringFactoriesLoader類,這個類實現了檢索META-INF/spring.factories文件,并獲取指定接口的配置的功能。在這個類中定義了兩個對外的方法:

  • loadFactories :根據接口類獲取其實現類的實例,這個方法返回的是對象列表。
  • loadFactoryNames :根據接口獲取其接口類的名稱,這個方法返回的是類名的列表。

上面的兩個方法的關鍵都是從指定的ClassLoader中獲取spring.factories文件,并解析得到類名列表,具體代碼如下:

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}try {Enumeration<URL> urls = (classLoader != null ?//遍歷整個ClassLoader中所有jar包下的spring.factories文件classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryClassName = ((String) entry.getKey()).trim();for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryClassName, factoryName.trim());}}}cache.put(classLoader, result);return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);}}

從代碼中我們可以知道,在這個方法中會遍歷整個ClassLoader中所有jar包下的spring.factories文件。也就是說我們可以在自己的jar中配置spring.factories文件,不會影響到其它地方的配置,也不會被別人的配置覆蓋。spring.factories的是通過Properties解析得到的,所以我們在寫文件中的內容都是安裝下面這種方式配置的:

com.xxx.interface=com.xxx.classname

如果一個接口希望配置多個實現類,可以使用’,’進行分割。

四、spring-boot包中的spring.factories文件

在Spring Boot的很多包中都能夠找到spring.factories文件,下面就是spring-boot包中的spring.factories文件

# PropertySource Loaders org.springframework.boot.env.PropertySourceLoader=\ org.springframework.boot.env.PropertiesPropertySourceLoader,\ org.springframework.boot.env.YamlPropertySourceLoader# Run Listeners org.springframework.boot.SpringApplicationRunListener=\ org.springframework.boot.context.event.EventPublishingRunListener# Error Reporters org.springframework.boot.SpringBootExceptionReporter=\ org.springframework.boot.diagnostics.FailureAnalyzers# Application Context Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\ org.springframework.boot.context.ContextIdApplicationContextInitializer,\ org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\ org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer# Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.ClearCachesApplicationListener,\ org.springframework.boot.builder.ParentContextCloserApplicationListener,\ org.springframework.boot.context.FileEncodingApplicationListener,\ org.springframework.boot.context.config.AnsiOutputApplicationListener,\ org.springframework.boot.context.config.ConfigFileApplicationListener,\ org.springframework.boot.context.config.DelegatingApplicationListener,\ org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\ org.springframework.boot.context.logging.LoggingApplicationListener,\ org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener# Environment Post Processors org.springframework.boot.env.EnvironmentPostProcessor=\ org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\ org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\ org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor# Failure Analyzers org.springframework.boot.diagnostics.FailureAnalyzer=\ org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer# FailureAnalysisReporters org.springframework.boot.diagnostics.FailureAnalysisReporter=\ org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

在日常工作中,我們可能需要實現一些SDK或者Spring Boot Starter給被人使用時,我們就可以使用Factories機制。Factories機制可以讓SDK或者Starter的使用只需要很少或者不需要進行配置,只需要在服務中引入我們的jar包即可。

五、Spring Boot 之spring.factories加載第三方的Bean

  • 首先拋出一個問題:如果想要被Spring容器管理的Bean的路徑不再Spring Boot 的包掃描路徑下,怎么辦呢?也就是如何去加載第三方的Bean 呢?
  • 這里我們使用Swagger的配置來做實驗。

    • 首先一個Swagger的配置類:SwaggerConfig
    //SwaggerConfig 代碼: @Configuration @EnableSwagger2 public class SwaggerConfig implements EnvironmentAware {private static final Logger log = LoggerFactory.getLogger(SwaggerConfig.class);@Autowiredprivate Environment env;@Value("${swagger.scan.package}")private String swaggerScanPackage;public SwaggerConfig() {}@Beanpublic Docket createRestApi() {Predicate<String> path = PathSelectors.any();if (Arrays.asList(this.env.getActiveProfiles()).contains("prod")) {path = PathSelectors.none();}log.info("####初始化createRestApi####swaggerScanPackage:" + this.swaggerScanPackage);log.info(path.toString());return (new Docket(DocumentationType.SWAGGER_2)).apiInfo(this.apiInfo()).select().apis(RequestHandlerSelectors.basePackage(this.swaggerScanPackage)).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {log.info("##################################初始化API信息################################################");return (new ApiInfoBuilder()).title("APIs").description("…………").termsOfServiceUrl("https://js.dazhi.loan.com").version("1.0").build();}@Overridepublic void setEnvironment(Environment environment) {} }

    2:再看我的工程結構吧:

    發現我的SwaggerConfig 類和 SpringBoot 的啟動類ConfigApplication.java 不在同一級目錄下,所以當Spring Boot 自動掃描包的時候,是掃描不到我的SwaggerConfig 的配置的,也就在控制臺沒有Swagger的打印的信息:

    所以這時候我如果想要把SwaggerConfig 加載到Spring容器中的話 要怎么辦呢?下面介紹兩種方式

    • ①:在Spring Boot Application 主類上 使用@Import 注解

      啟動就可以看到Swagger的基礎信息:

    • ②:現在我們將其改造一下,采用spring.factories 的方式去加載SwaggerConfig類,在resources目錄下新建一個META-INF 的目錄,然后在新建一個spring.factories 的文件,里面的內容為:

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.sg.config.SwaggerConfig

    然后在把Spring Boot 啟動類上的@Import注釋掉,啟動發現也可以把SwaggerConfig加載到Spring 容器中

    到這就完成了加載一個Spring 不能掃描到的一個類,他可以是第三方的,也可以是自己寫的,只要是Spring Boot 默認掃描路徑不能夠掃描到,都可以使用這種方式去加載。

    com.sg.config.SwaggerConfig 可以當作是一個自定義配置文件,里面也可以添加 @Configuration @ComponentScan("xxx")

    等配置,掃描指定目錄下Service或Bean.

    文章轉自

    總結

    以上是生活随笔為你收集整理的SpringBoot解耦的扩展机制 Spring Factories介绍及使用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 北条麻妃av在线播放 | 少妇大叫太粗太大爽一区二区 | 免费在线不卡视频 | 国产精品99久 | 影音先锋中文字幕在线视频 | 宝贝乖h调教灌尿穿环 | 亚洲精品aⅴ中文字幕乱码 国产精品调教视频 | 亚洲精选av | 欧美老少做受xxxx高潮 | 欧美videossex极品 | 无码人妻一区二区三区精品视频 | 91网页入口 | 日本成人性爱 | 国产又黄又粗又硬 | 人妻丰满熟妇无码区免费 | 91一区二区在线观看 | 亚洲精品第一 | 久久亚洲国产精品 | 欧美日免费 | 日本天堂在线播放 | 91视频免费在观看 | 在线综合视频 | av免费国产 | 一级黄色录相 | 国产女人爽到高潮a毛片 | 中文字幕在线观看视频网站 | 国产福利视频一区二区三区 | 日韩一区二区在线观看 | 天天艹av | 欧美1级片 | 91美女在线 | 91视频最新入口 | 在线不卡毛片 | 国产尤物在线 | 精品国产一区二区在线观看 | 被室友玩屁股(h)男男 | 大度亲吻原声视频在线观看 | 欧美被狂躁喷白浆精品 | 女人下面流白浆的视频 | 国产欧美精品一区二区三区 | 男人天堂av电影 | 伊人99热| 日韩中文字幕综合 | 国产大片中文字幕在线观看 | 亚洲国产极品 | xxxxx在线| 美丽的姑娘观看在线播放 | 性猛交xxxx乱大交孕妇2十 | 无码国产伦一区二区三区视频 | 久久免费精品视频 | 欧美日韩精品电影 | 毛片在线网站 | 成年网站在线观看 | 欧美三级色图 | 级毛片 | 国产熟女高潮一区二区三区 | 欧美视频直播网站 | 日本激情在线 | 国产免费看av | 亚洲香蕉在线 | 国产二区视频在线观看 | 天堂中文在线网 | 男人午夜剧场 | 思思99热| 熟女毛毛多熟妇人妻aⅴ在线毛片 | 麻豆视频在线观看免费网站黄 | 亚洲激情免费视频 | 亚洲精品第一页 | 国产一区二区精彩视频 | 激情小说视频在线 | 亚洲综合色在线观看 | 一区二区三区激情 | 久久久久亚洲av成人无码电影 | 一级肉体全黄毛片 | 国产视频一区在线播放 | 在线免费看av | 女同性恋一区二区三区 | 色视频线观看在线播放 | 影音先锋中文字幕在线视频 | 午夜窝窝 | 成人黄色网页 | 欧美日韩午夜爽爽 | 国产精品中文在线 | 精品一区日韩 | 国产中文字幕在线免费观看 | 免费裸体视频女性 | 蜜臀av性久久久久蜜臀aⅴ麻豆 | 美女视频黄免费 | 美景之屋电影免费高清完整韩剧 | 先锋影音av中文字幕 | 国产香蕉久久 | 波多野结av衣东京热无码专区 | 啪啪视屏 | 欧美乱轮视频 | 日韩大片在线观看 | 免费看黄色片网站 | 国语对白对话在线观看 | 李丽珍裸体午夜理伦片 | 亚洲AV无码精品黑人黑人 |