SpringBoot自動(dòng)配置深入探究實(shí)現(xiàn)原理
說(shuō)明:在閱讀本篇文章之前建議大家先詳細(xì)學(xué)習(xí)一下spring的相關(guān)知識(shí),有助于更深刻的理解spirngboot的配置原理。
一、什么是springboot自動(dòng)配置
SpringBoot通過(guò)@EnableAutoConfiguration注解開(kāi)啟自動(dòng)配置,對(duì)jar包下的spring.factories文件進(jìn)行掃描,這個(gè)文件中包含了可以進(jìn)行自動(dòng)配置的類,當(dāng)滿足@Condition注解指定的條件時(shí),便在依賴的支持下進(jìn)行實(shí)例化,注冊(cè)到Spring容器中。
通俗的來(lái)講,我們之前在寫ssm項(xiàng)目時(shí)候,配置了大量坐標(biāo)和配置內(nèi)容,搭環(huán)境的過(guò)程在項(xiàng)目開(kāi)發(fā)中占據(jù)了大量時(shí)間,SpringBoot的最大的特點(diǎn)就是簡(jiǎn)化了各種xml配置內(nèi)容,所以springboot的自動(dòng)配置就是用注解來(lái)對(duì)一些常規(guī)的配置做默認(rèn)配置,簡(jiǎn)化xml配置內(nèi)容,使你的項(xiàng)目能夠快速運(yùn)行。
springboot核心配置原理:
- 自動(dòng)配置類都存放在spring-boot-autoconfigure-版本號(hào).jar下的org.springframework.boot.autoconfigure中
- 當(dāng)我們?cè)赼pplication.properties中配置debug=true后啟動(dòng)容器??梢钥吹椒?wù)器初始化的初始化配置
- DispatcherServletAutoConfigratio注冊(cè)前端控制器
- EmbeddedServletContainerAutoConfiguration注冊(cè)容器類型
- HttpMessageConvertersAutoConfiguration注冊(cè)json或者xml處理器
- JacksonAutoConfiguration注冊(cè)json對(duì)象解析器
- 如果加入其他功能的依賴,springBoot還會(huì)實(shí)現(xiàn)這些功能的自動(dòng)配置
二、Starter組件
Starter組件是可被加載在應(yīng)用中的Maven依賴項(xiàng)項(xiàng)。只有在Maven配置中添加對(duì)應(yīng)的依賴配置,即可使用對(duì)應(yīng)的Starter組件。例如,添加spring-boot-starter-web依賴,就可以用于構(gòu)建RESTAPI服務(wù),其包含了SpringMVC和Tomcat內(nèi)嵌容器。
一個(gè)完整的Starter組件包括以下兩點(diǎn):
- 提供自動(dòng)配置功能的自動(dòng)配置模塊
- 提供依賴關(guān)系管理崗功能的組件模塊,即封裝了組件所有功能,開(kāi)箱即用。
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的方式進(jìn)行配置。
@EnableAutoConfiguration:本文重點(diǎn)講解,主要用于開(kāi)啟自動(dòng)配置。
@ComponentScan:自動(dòng)掃描組件,默認(rèn)掃描該類所在包及其子包下所有帶有指定注解的類,將它們自動(dòng)裝配到bean容器中,會(huì)被自動(dòng)裝配的注解包括@Controller、@Service、@Component、@Repository等。也可以指定掃描路徑。
四、@EnableAutoConfiguration
這個(gè)注解是幫助我們自動(dòng)加載默認(rèn)配置的,它里面有兩個(gè)關(guān)鍵注解@AutoConfigurationPackage和@Import,我們來(lái)詳細(xì)了解@Import注解。
@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { //檢查自動(dòng)配置功能是否開(kāi)啟,默認(rèn)開(kāi)啟 if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } //加載自動(dòng)配置的元信息 AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = getAttributes(annotationMetadata); //獲取候選配置類 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); //去掉重復(fù)的配置類 configurations = removeDuplicates(configurations); //獲得注解中被exclude和excludeName排除的類的集合 Set<String> exclusions = getExclusions(annotationMetadata, attributes); //檢查被排除類是否可實(shí)例化、是否被自動(dòng)注冊(cè)配置所使用,不符合條件則拋出異常 checkExcludedClasses(configurations, exclusions); //從候選配置類中去除掉被排除的類 configurations.removeAll(exclusions); //過(guò)濾 configurations = filter(configurations, autoConfigurationMetadata); //將配置類和排除類通過(guò)事件傳入到監(jiān)聽(tīng)器中 fireAutoConfigurationImportEvents(configurations, exclusions); //最終返回符合條件的自動(dòng)配置類的全限定名數(shù)組 return StringUtils.toStringArray(configurations);
@Import(AutoConfigurationImportSelector.class)注解,這里導(dǎo)入AutoConfigurationImportSelector類。這個(gè)類中有一個(gè)非常重要的方法——selectImports(),它幾乎涵蓋了組件自動(dòng)裝配的所有處理邏輯,包括獲得候選配置類、配置類去重、排除不需要的配置類、過(guò)濾等,最終返回符合條件的自動(dòng)配置類的全限定名數(shù)組。
五、SpringFactoriesLoader
spring-core包里定義了SpringFactoriesLoader類,這個(gè)類實(shí)現(xiàn)了檢索META-INF/spring.factories文件,并獲取指定接口的配置的功能。在這個(gè)類中定義了兩個(gè)對(duì)外的方法:
- loadFactories根據(jù)接口類獲取其實(shí)現(xiàn)類的實(shí)例,這個(gè)方法返回的是對(duì)象列表。
- loadFactoryNames根據(jù)接口獲取其接口類的名稱,這個(gè)方法返回的是類名的列表。
上面的兩個(gè)方法的關(guān)鍵都是從指定的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); } }
由代碼可知,在這個(gè)方法中會(huì)遍歷整個(gè)ClassLoader中所有jar包下的spring.factories文件。也就是說(shuō)我們可以在自己的jar中配置spring.factories文件,不會(huì)影響到其它地方的配置,也不會(huì)被別人的配置覆蓋。
spring.factories的是通過(guò)Properties解析得到的,所以我們?cè)趯懳募械膬?nèi)容都是安裝下面這種方式配置的:
com.xxx.interface=com.xxx.classname
最后希望大家在學(xué)習(xí)的過(guò)程中,能夠多了解實(shí)現(xiàn)各種功能的基本原理,有助于提高學(xué)習(xí)效率。
到此這篇關(guān)于SpringBoot自動(dòng)配置深入探究實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)SpringBoot自動(dòng)配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis-Plus實(shí)現(xiàn)公共字段自動(dòng)填充功能詳解
在開(kāi)發(fā)中經(jīng)常遇到多個(gè)實(shí)體類有共同的屬性字段,這些字段屬于公共字段,也就是很多表中都有這些字段,能不能對(duì)于這些公共字段在某個(gè)地方統(tǒng)一處理,來(lái)簡(jiǎn)化開(kāi)發(fā)呢?MyBatis-Plus就提供了這一功能,本文就來(lái)為大家詳細(xì)講講2022-08-08解決IDEA中maven導(dǎo)入jar包一直報(bào)錯(cuò)問(wèn)題
這篇文章主要介紹了解決IDEA中maven導(dǎo)入jar包一直報(bào)錯(cuò)問(wèn)題,本文通過(guò)實(shí)例圖文的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Java中的HashMap為什么會(huì)產(chǎn)生死循環(huán)
這篇文章主要介紹了Java中的HashMap為什么會(huì)產(chǎn)生死循環(huán),HashMap?死循環(huán)是一個(gè)比較常見(jiàn)、比較經(jīng)典的問(wèn)題,下面文章我們就來(lái)徹底理解死循環(huán)的原因。需要的小伙伴可以參考一下2022-05-05