關于spring.factories的常用配置項說明
概述
spring.factories 實現(xiàn)是依賴 spring-core 包里的 SpringFactoriesLoader 類,這個類實現(xiàn)了檢索 META-INF/spring.factories 文件,并獲取指定接口的配置的功能。
Spring Factories機制提供了一種解耦容器注入的方式,幫助外部包(獨立于spring-boot項目)注冊Bean到spring boot項目容器中。
spring.factories 這種機制實際上是仿照 java 中的 SPI 擴展機制實現(xiàn)的。
Spring Factories機制原理
核心類SpringFactoriesLoader
從上文可知,Spring Factories機制通過META-INF/spring.factories文件獲取相關的實現(xiàn)類的配置信息,而SpringFactoriesLoader的功能就是讀取META-INF/spring.factories,并加載配置中的類。
SpringFactoriesLoader主要有兩個方法:loadFactories和loadFactoryNames。
- loadFactoryNames
用于按接口獲取Spring Factories文件中的實現(xiàn)類的全稱,其方法定義如下所示,其中參數(shù)factoryType指定了需要獲取哪個接口的實現(xiàn)類,classLoader用于讀取配置文件資源。
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader)
- loadFactories
用于按接口獲取Spring Factories文件中的實現(xiàn)類的實例,其方法定義如下所示,其中參數(shù)factoryType指定了需要獲取哪個接口的實現(xiàn)類,classLoader用于讀取配置文件資源和加載類。
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader)
用法及配置
spring.factories 文件必須放在 resources 目錄下的 META-INF 的目錄下,否則不會生效。
如果一個接口希望配置多個實現(xiàn)類,可以用","分割。
BootstrapConfiguration
該配置項用于自動引入配置源,類似于spring-cloud的bootstrap和nacos的配置,通過指定的方式加載我們自定義的配置項信息。
該配置項配置的類必須是實現(xiàn)了PropertySourceLocator接口的類。
org.springframework.cloud.bootstrap.BootstrapConfiguration=\ xxxxxx.configure.config.ApplicationConfigure
public class ApplicationConfigure { @Bean @ConditionalOnMissingBean({CoreConfigPropertySourceLocator.class}) public CoreConfigPropertySourceLocator configLocalPropertySourceLocator() { return new CoreConfigPropertySourceLocator(); } } public class CoreConfigPropertySourceLocator implements PropertySourceLocator { ..... }
ApplicationContextInitializer
該配置項用來配置實現(xiàn)了 ApplicationContextInitializer 接口的類,這些類用來實現(xiàn)上下文初始化
org.springframework.context.ApplicationContextInitializer=\ xxxxxx.config.TestApplicationContextInitializer
public class TestApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("TestApplicationContextInitializer.initialize() " + applicationContext); } }
ApplicationListener
配置應用程序監(jiān)聽器,該監(jiān)聽器必須實現(xiàn) ApplicationListener 接口。
它可以用來監(jiān)聽 ApplicationEvent 事件。
org.springframework.context.ApplicationListener=\ xxxxxxx.factories.listener.TestApplicationListener
@Slf4j public class TestApplicationListener implements ApplicationListener<TestMessageEvent> { @Override public void onApplicationEvent(EmailMessageEvent event) { log.info("模擬消息事件... "); log.info("TestApplicationListener 接受到的消息:{}", event.getContent()); } }
AutoConfigurationImportListener
該配置項用來配置自動配置導入監(jiān)聽器,監(jiān)聽器必須實現(xiàn) AutoConfigurationImportListener 接口。
該監(jiān)聽器可以監(jiān)聽 AutoConfigurationImportEvent 事件。
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ xxxx.config.TestAutoConfigurationImportListener
public class TestAutoConfigurationImportListener implements AutoConfigurationImportListener { @Override public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) { System.out.println("TestAutoConfigurationImportListener.onAutoConfigurationImportEvent() " + event); } }
AutoConfigurationImportFilter
配置自動配置導入過濾器,過濾器必須實現(xiàn) AutoConfigurationImportFilter 接口。
該過濾器用來過濾那些自動配置類可用。
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ xxxxxx.config.TestConfigurationCondition
public class TestConfigurationCondition implements AutoConfigurationImportFilter { @Override public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) { System.out.println("TestConfigurationCondition.match() autoConfigurationClasses=" + Arrays.toString(autoConfigurationClasses) + ", autoConfigurationMetadata=" + autoConfigurationMetadata); return new boolean[0]; } }
EnableAutoConfiguration
配置自動配置類。
這些配置類需要添加 @Configuration 注解,可用于注冊bean。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ xxxxx.config.TestConfiguration
@Configuration public class MyConfiguration { public MyConfiguration() { System.out.println("MyConfiguration()"); } @Bean public Testbean testbean(){ return new Testbean() } //注冊過濾器 @Bean public TestFilter testFilter(){ return new TestFilter() } }
FailureAnalyzer
配置自定的錯誤分析類,該分析器需要實現(xiàn) FailureAnalyzer 接口。
org.springframework.boot.diagnostics.FailureAnalyzer=\ xxxxx.config.TestFailureAnalyzer
/** * 自定義錯誤分析器 */ public class TestFailureAnalyzer implements FailureAnalyzer { @Override public FailureAnalysis analyze(Throwable failure) { System.out.println("TestFailureAnalyzer.analyze() failure=" + failure); return new FailureAnalysis("TestFailureAnalyzer execute", "test spring.factories", failure); } }
TemplateAvailabilityProvider
配置模板的可用性提供者,提供者需要實現(xiàn) TemplateAvailabilityProvider 接口。
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\ xxxxx.config.TestTemplateAvailabilityProvider
/** * 驗證指定的模板是否支持 */ public class TestTemplateAvailabilityProvider implements TemplateAvailabilityProvider { @Override public boolean isTemplateAvailable(String view, Environment environment, ClassLoader classLoader, ResourceLoader resourceLoader) { System.out.println("TestTemplateAvailabilityProvider.isTemplateAvailable() view=" + view + ", environment=" + environment + ", classLoader=" + classLoader + "resourceLoader=" + resourceLoader); return false; } }
自定義Spring Factories機制
首先我們需要先定義兩個模塊,第一個模塊A用于定義interface和獲取interface的實現(xiàn)類。
代碼如下:
package com.zhong.spring.demo.demo_7_springfactories; public interface DemoService { void printName(); } package com.zhong.spring.demo.demo_7_springfactories; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.List; @Slf4j @Service public class DemoServiceFactory { @PostConstruct public void printService(){ List<String> serviceNames = SpringFactoriesLoader.loadFactoryNames(DemoService.class,null); for (String serviceName:serviceNames){ log.info("name:" + serviceName); } List<DemoService> services = SpringFactoriesLoader.loadFactories(DemoService.class,null); for (DemoService demoService:services){ demoService.printName(); } } }
另一個模塊B引入A模塊,并實現(xiàn)DemoService類。并且配置spring.factories
代碼如下:
package com.zhong.spring.usuldemo.impl; import com.zhong.spring.demo.demo_7_springfactories.DemoService; import lombok.extern.slf4j.Slf4j; @Slf4j public class DemoServiceImpl1 implements DemoService { @Override public void printName() { log.info("-----------DemoServiceImpl2------------"); } } import com.zhong.spring.demo.demo_7_springfactories.DemoService; import lombok.extern.slf4j.Slf4j; @Slf4j public class DemoServiceImpl2 implements DemoService { @Override public void printName() { log.info("-----------DemoServiceImpl2------------"); } }
spring.factory配置如下:
com.zhong.spring.demo.demo_7_springfactories.DemoService=\ com.zhong.spring.usuldemo.impl.DemoServiceImpl1,\ com.zhong.spring.usuldemo.impl.DemoServiceImpl2
啟動模塊B
得到以下日志;
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
詳解Java阻塞隊列(BlockingQueue)的實現(xiàn)原理
這篇文章主要介紹了詳解Java阻塞隊列(BlockingQueue)的實現(xiàn)原理,阻塞隊列是Java util.concurrent包下重要的數(shù)據(jù)結(jié)構(gòu),有興趣的可以了解一下2017-06-06MyBatis-Flex BaseMapper的接口基本用法小結(jié)
本文主要介紹了MyBatis-Flex BaseMapper的接口基本用法小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-02-02SpringBoot整合MQTT并實現(xiàn)異步線程調(diào)用的問題
這篇文章主要介紹了基于SpringBoot通過注解實現(xiàn)對mqtt消息處理的異步調(diào)用,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-11-11