SpringBoot自動配置深入探究實現原理
說明:在閱讀本篇文章之前建議大傢先詳細學習一下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自動配置內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Spring中的spring.factories文件用法(Spring如何加載第三方Bean)
- Java SpringBoot自動裝配原理詳解及源碼註釋
- SpringBoot原理之自動配置機制詳解
- SpringBoot自動配置原理分析
- Springboot @Configuration與自動配置詳解