首頁 > 軟體

SpringBoot自動設定深入探究實現原理

2022-08-15 22:04:09

說明:在閱讀本篇文章之前建議大家先詳細學習一下spring的相關知識,有助於更深刻的理解spirngboot的設定原理。

一、什麼是springboot自動設定

SpringBoot通過@EnableAutoConfiguration註解開啟自動設定,對jar包下的spring.factories檔案進行掃描,這個檔案中包含了可以進行自動設定的類,當滿足@Condition註解指定的條件時,便在依賴的支援下進行範例化,註冊到Spring容器中。

通俗的來講,我們之前在寫ssm專案時候,設定了大量座標和設定內容,搭環境的過程在專案開發中佔據了大量時間,SpringBoot的最大的特點就是簡化了各種xml設定內容,所以springboot的自動設定就是用註解來對一些常規的設定做預設設定,簡化xml設定內容,使你的專案能夠快速執行。

springboot核心設定原理:

  • 自動設定類都存放在spring-boot-autoconfigure-版本號.jar下的org.springframework.boot.autoconfigure中
  • 當我們在application.properties中設定debug=true後啟動容器。可以看到伺服器初始化的初始化設定
  • DispatcherServletAutoConfigratio註冊前端控制器
  • EmbeddedServletContainerAutoConfiguration註冊容器型別
  • HttpMessageConvertersAutoConfiguration註冊json或者xml處理器
  • JacksonAutoConfiguration註冊json物件解析器
  • 如果加入其他功能的依賴,springBoot還會實現這些功能的自動設定

二、Starter元件

Starter元件是可被載入在應用中的Maven依賴項項。只有在Maven設定中新增對應的依賴設定,即可使用對應的Starter元件。例如,新增spring-boot-starter-web依賴,就可以用於構建RESTAPI服務,其包含了SpringMVC和Tomcat內嵌容器。

一個完整的Starter元件包括以下兩點:

  • 提供自動設定功能的自動設定模組
  • 提供依賴關係管理崗功能的元件模組,即封裝了元件所有功能,開箱即用。

spring-boot-starter-web依賴原始碼

package org.springframework.boot.autoconfigure.web.servlet;
@Configuration
@ConditionalOnClass({ServletRequest.class})
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@EnableConfigurationProperties({ServerProperties.class})
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class})
public class ServletWebServerFactoryAutoConfiguration {
    ......
}
@

三、三大註解

@SpringBootConfiguration:繼承自Configuration,支援JavaConfig的方式進行設定。

@EnableAutoConfiguration:本文重點講解,主要用於開啟自動設定。

@ComponentScan:自動掃描元件,預設掃描該類所在包及其子包下所有帶有指定註解的類,將它們自動裝配到bean容器中,會被自動裝配的註解包括@Controller、@Service、@Component、@Repository等。也可以指定掃描路徑。

四、@EnableAutoConfiguration

這個註解是幫助我們自動載入預設設定的,它裡面有兩個關鍵註解@AutoConfigurationPackage和@Import,我們來詳細瞭解@Import註解。

@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		//檢查自動設定功能是否開啟,預設開啟
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		//載入自動設定的元資訊
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		//獲取候選設定類
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
		//去掉重複的設定類
		configurations = removeDuplicates(configurations);
		//獲得註解中被exclude和excludeName排除的類的集合
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		//檢查被排除類是否可範例化、是否被自動註冊設定所使用,不符合條件則丟擲異常
		checkExcludedClasses(configurations, exclusions);
		//從候選設定類中去除掉被排除的類
		configurations.removeAll(exclusions);
		//過濾
		configurations = filter(configurations, autoConfigurationMetadata);
		//將設定類和排除類通過事件傳入到監聽器中
		fireAutoConfigurationImportEvents(configurations, exclusions);
		//最終返回符合條件的自動設定類的全限定名陣列
		return StringUtils.toStringArray(configurations);

@Import(AutoConfigurationImportSelector.class)註解,這裡匯入AutoConfigurationImportSelector類。這個類中有一個非常重要的方法——selectImports(),它幾乎涵蓋了元件自動裝配的所有處理邏輯,包括獲得候選設定類、設定類去重、排除不需要的設定類、過濾等,最終返回符合條件的自動設定類的全限定名陣列。

五、SpringFactoriesLoader

spring-core包裡定義了SpringFactoriesLoader類,這個類實現了檢索META-INF/spring.factories檔案,並獲取指定介面的設定的功能。在這個類中定義了兩個對外的方法:

  • loadFactories根據介面類獲取其實現類的範例,這個方法返回的是物件列表。
  • loadFactoryNames根據介面獲取其介面類的名稱,這個方法返回的是類名的列表。

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

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
    String factoryClassName = factoryClass.getName();
    try {
        Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
        List<String> result = new ArrayList<String>();
        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
            String factoryClassNames = properties.getProperty(factoryClassName);
            result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
        }
        return result;
    }
    catch (IOException ex) {
        throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
                "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
    }
}

由程式碼可知,在這個方法中會遍歷整個ClassLoader中所有jar包下的spring.factories檔案。也就是說我們可以在自己的jar中設定spring.factories檔案,不會影響到其它地方的設定,也不會被別人的設定覆蓋。

spring.factories的是通過Properties解析得到的,所以我們在寫檔案中的內容都是安裝下面這種方式設定的:

com.xxx.interface=com.xxx.classname

最後希望大家在學習的過程中,能夠多瞭解實現各種功能的基本原理,有助於提高學習效率。

到此這篇關於SpringBoot自動設定深入探究實現原理的文章就介紹到這了,更多相關SpringBoot自動設定內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com