日韩性视频-久久久蜜桃-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电影 | 91色综合| www日本高清视频 | 深夜福利一区 | 波多野结衣高清电影 | 日日日噜噜噜 | 一区二区三区视频在线播放 | 国产不卡一 | 免费视频久久 | 欧美一级鲁丝片 | 精品国产乱码一区二区三区99 | 国产一区二区三区免费观看视频 | 开心激情深爱 | 日本亚洲黄色 | 欧美一区二区三区在线视频 | 亚洲国产麻豆 | 伊人久久久久久久久久久久久 | 三级黄色免费 | 性做久久久久 | 日韩淫片| 国产簧片 | aaa午夜| 好吊妞在线观看 | 久久亚洲综合国产精品99麻豆精品福利 | 国产一区色 | 18精品爽国产白嫩精品 | 亚洲精品国产日韩 | 久久理论视频 | 成人欧美一区二区三区黑人动态图 | 精品一区二区三区成人免费视频 | 中文无码精品一区二区三区 | 韩日视频| aaa特级毛片 | 又黄又刺激的视频 | 欧美日韩综合一区二区三区 | a爱视频| 亚洲熟女一区二区 | 伊人狼人综合 | 国产麻豆精品久久一二三 | 四房婷婷| 污片视频在线观看 | 国产精品久久久久久久久借妻 | 免费看a级片 | 国产色图视频 | 九九视频在线播放 | 青青视频免费 | 自宅警备员在线观看 | 国产乱码一区二区 | 亚洲第一二三四区 | 2022精品国偷自产免费观看 | 国产精品自拍99 | ,午夜性刺激免费看视频 | 91丨porny在线| 中字av在线 | 97国产精东麻豆人妻电影 | 国产精选网站 | 久久久久人妻精品一区二区三区 | 九九久久综合 | av最新网| 欧美性猛交ⅹxx | 亚洲欧美高清在线 | 精品成人一区二区三区久久精品 | 麻豆91视频 | 天天操天天操天天操天天操天天操 | 亚洲视频精品一区 | 国产精品久久久久久久久久久久久久久久久久 | 国产又好看的毛片 | 婷婷日| 天天色天天干天天色 | 自拍毛片 | 日韩一级片在线 | 一区二区三区四区在线播放 | jzjzjzjzj亚洲成熟少妇 | 国内一区二区三区 | 曰本无码人妻丰满熟妇啪啪 | www.99re7.com| 毛片在哪里看 | 中日韩男男gay无套 人人草人人干 | 91丨九色 | 久久香蕉影院 | 五月天导航 | 欧美激情免费在线 | 美女热逼 | 午夜视频在线观看国产 | 日日狠狠久久 | 中文在线字幕免费观看 | 密色av| 久久久精品电影 | 污污在线免费观看 | 日韩三级中文 | 日日摸日日碰 | 爱情岛论坛亚洲品质自拍 | 久久影 | 天天躁狠狠躁 | 国产jzjzjz丝袜老师水多 | 中日韩毛片 |