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

歡迎訪問 生活随笔!

生活随笔

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

javascript

Spring Boot 扩展点应用之工厂加载机制

發布時間:2023/12/13 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Boot 扩展点应用之工厂加载机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Spring 工廠加載機制,即 Spring Factories Loader,核心邏輯是使用 SpringFactoriesLoader 加載由用戶實現的類,并配置在約定好的META-INF/spring.factories 路徑下,該機制可以為框架上下文動態的增加擴展。
該機制類似于 Java SPI,給用戶提供可擴展的鉤子,從而達到對框架的自定義擴展功能。

核心實現類 SpringFactoriesLoader

SpringFactoriesLoader 是 Spring 工廠加載機制的核心底層實現類。它的主要作用是 從 META-INF/spring.factories 路徑下加載指定接口的實現類。該文件可能存在于工程類路徑下或者 jar 包之內,所以會存在多個該文件。

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

SpringFactoriesLoader loadFactories load 并從 FACTORIES_RESOURCE_LOCATION文件中實例化給定類型的工廠實現類。 spring.factories 文件必須采用 Properties 格式,其中鍵是接口或抽象類的完全限定*名稱,值是逗號分隔的實現類名稱列表。例如:

該文件的格式,Key 必須為接口或抽象類的全限定名,value 為 具體的實現類,多個以 逗號分隔。類似如下配置:

# 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

從該文件中我們可以看到,其中 ApplicationContextInitializer 為父類,value為實現類,以逗號分隔。

SpringFactoriesLoader 源碼分析

Spring Boot 完成自動裝配的核心之一就是工廠加載機制。我們以 Spring Boot 的自動裝配為例來分析。如果要開啟 Spring 的自動裝配功能,會使用 @EnableAutoConfiguration 這個注解,這個注解會 Import AutoConfigurationImportSelector 這個類。

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {
AutoConfigurationImportSelector 中有一個方法就是加載 EnableAutoConfiguration 為 key 的實現配置類。
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class,this.beanClassLoader) }
SpringFactoriesLoader loadFactories 加載 所有以 factoryClass 為 Key 的實現類
public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {// 省略部分前置判斷和 logger 代碼 ClassLoader classLoaderToUse = classLoader;if (classLoaderToUse == null) {classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();}//根據當前接口類的全限定名作為key,從loadFactoryNames從文件中獲取到所有實現類的全限定名List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);List<T> result = new ArrayList<>(factoryNames.size());//實例化所有實現類,并保存到 result 中返回。for (String factoryName : factoryNames) {result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));}AnnotationAwareOrderComparator.sort(result);return result;}
調用 loadSpringFactories 從META-INF/spring.factories文件中進行加載

從文件中讀取接口和實現類的邏輯,返回 Map<String, List<String>>

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}try {//FACTORIES_RESOURCE_LOCATION --> META-INF/spring.factoriesEnumeration<URL> urls = (classLoader != null ?classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));//一Key多值 Map,適合上文提到的一個接口多個實現類的情形。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()) {//以逗號進行分割,得到List的實現類全限定名集合List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));result.addAll((String) entry.getKey(), factoryClassNames);}}cache.put(classLoader, result);//返回return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);} }

總結

上面通過以 Spring Boot 的自動裝配為例,我們分析了 Spring 工廠加載機制的整個過程,重點分析了SpringFactoriesLoader類。通過這樣的機制,我們可以十分的方便的為框架提供各式各樣的擴展插件,我們可以自己定義自己的組件的自動裝配配置類,然后通過工廠加載機制讓 Spring 進行加載并得到自動裝配。

工廠加載機制的應用 ApplicationContextInitializer

ApplicationContextInitializer 是在 Spring Boot 或者 Spring Mvc 啟動過程中調用的。具體時機為Spring 應用上下文 refresh 之前(調用 refresh 方法)。

ApplicationContextInitializer 主要提供應用上下文未refresh之前的擴展,這時候可以對 ConfigurableApplicationContext 進行一些擴展處理等。

自定義一個類,實現 ApplicationContextInitializer ,并重寫 initialize 方法:

@Order(Ordered.HIGHEST_PRECEDENCE) public class HelloWorldApplicationContextInitializer implements ApplicationContextInitializer {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("=================> applicationContext: " + applicationContext.getId());} }

啟動 Spring Boot 程序,我們可以看到在 refresh 之前,會在控制臺打印上面這句話。

  • 另外的實現方式:
    • application.properties添加配置方式:
context.initializer.classes=com.maple.spring.initializer.AfterHelloWorldApplicationContextInitializer

對于這種方式是通過 DelegatingApplicationContextInitializer 這個初始化類中的 initialize 方法獲取到 application.properties 中 context.initializer.classes 對應的實現類,并對該實現類進行加載。

3.在 SpringApplication 中直接添加

public static void main(String[] args) {new SpringApplicationBuilder(SpringBootDemo3Application.class).initializers(new AfterHelloWorldApplicationContextInitializer()).run(args);} }

Spring Boot 使用 工廠機制加載 ApplicationListener 實現類

# 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

總結

工廠加載機制是 Spring 動態加載實現類的一種方式,提前在擴展類中寫好對應自動配置類,我們可以完成自動裝配的效果。Spring Boot 自動裝配模塊其中的loader 自動配置實現類就是基于此實現的。
Spring Boot 的一些新特性幾乎用到的都是 Spring Framework 的核心特性。因此學習 Spring Boot ,歸根結底就是學習 Spring Framework 核心。它是所有 Spring 應用的基石,所以我們應該從上至下,由淺入深來進行學習和分析。

轉載于:https://www.cnblogs.com/leihuazhe/p/9751836.html

總結

以上是生活随笔為你收集整理的Spring Boot 扩展点应用之工厂加载机制的全部內容,希望文章能夠幫你解決所遇到的問題。

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