點進去源碼發現html
先來看看每一個註解的意思java
能夠發現它是由衆多註解組合而成的,下面具體分析下這裏每一個註解所起到的做用。spring
@Retention Retention(保留)註解說明,這種類型的註解會被保留到那個階段. 有三個值:springboot
<context:component-scan>
,可以使用basePackages屬性指定要掃描的包,及掃描的條件。若是不設置則默認掃描@ComponentScan註解所在類的同級類和同級目錄下的全部類,因此咱們的Spring Boot項目,通常會把入口類放在頂層目錄中,這樣就可以保證源碼目錄下的全部類都可以被掃描到。@EnableAutoConfiguration 這個註解是讓Spring Boot的配置可以如此簡化的關鍵性註解。app
其實主要重要的註解就是標紅的這三個註解:下面咱們着重分析這三個註解。框架
1)@ComponentScan:就像上面所說,ComponentScan通常在spring中主要是用於:maven
@ComponentScan用於類或接口上主要是指定掃描路徑,spring會把指定路徑下帶有指定註解的類自動裝配到bean容器裏,會被自動裝配的註解包括@Controller、@Service、@Component、@Repository等等,其做用等同於<context:component-scan base-package="com.maple.learn" />配置。ide
而在springboot中,若是你的其餘包都在使用了@SpringBootApplication註解的main app所在的包及其下級包,則你什麼都不用作,SpringBoot會自動幫你把其餘包都掃描了,若是你有一些bean所在的包,不在main app的包及其下級包,那麼你須要手動加上@ComponentScan註解並指定那個bean所在的包。(後面在解釋在這裏的原理)spring-boot
2)@SpringBootConfiguration :先來一張其源碼截圖工具
這裏說明SpringBootConfiguration 實際上是對spring的@Configuration的封裝,至關於一個配置類,註解主要標註在某個類上,至關於xml配置文件中的<beans>。並會將當前類內聲明的一個或多個以@Bean註解的方法的實例歸入到spring容器中,而且實例名就是方法名。自己其實也是一個IoC容器的配置類。
3)@EnableAutoConfiguration 這個纔是重點,點擊源碼發現
先來聊聊這個註解:@AutoConfigurationPackage
AutoConfigurationPackage註解的做用是將 添加該註解的類所在的package 做爲 自動配置package 進行管理。
1 static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { 2 3 @Override 4 public void registerBeanDefinitions(AnnotationMetadata metadata, 5 BeanDefinitionRegistry registry) { 6 register(registry, new PackageImport(metadata).getPackageName()); 7 }
它實際上是註冊了一個Bean的定義。
new PackageImport(metadata).getPackageName(),它其實返回了當前主程序類的 同級以及子級 的包組件。
以上圖爲例,DemoApplication是和demo包同級,可是demo2這個類是DemoApplication的父級,和example包同級
也就是說,DemoApplication啓動加載的Bean中,並不會加載demo2,這也就是爲何,咱們要把DemoApplication放在項目的最高級中。
這裏來談談其與componentScan的區別:
在默認的狀況下就是將:主配置類(@SpringBootApplication
)的所在包及其子包裏邊的組件掃描到Spring容器中。
看看文檔的這句話:
it will be used when scanning for code @Entity classes.
It is generally recommended that you place EnableAutoConfiguration (if you’re
not using @SpringBootApplication) in a root package so that all sub-packages
and classes can be searched.
好比說,你用了Spring Data JPA,可能會在實體類上寫@Entity
註解。這個@Entity
註解由@AutoConfigurationPackage
掃描並加載,而咱們平時開發用的@Controller/@Service/@Component/@Repository
這些註解是由ComponentScan
來掃描並加載的。
簡單理解:這兩者掃描的對象是不同的。
4)下面來看看一個重中之重的註解:@EnableAutoConfiguration
老規矩進行這個重要註解以前,要先鋪墊一些其用到的知識,否則的話,不能到時候懵懵懂懂的。接下來看看這個@Import這個註解,他是來幹什麼的呢?
@Import註釋,根據字義,咱們能夠理解爲導入組件選擇器自動配置,做用是將須要導入的組件以全類名的方式返回,這些組件將被添加到Spring容器中,如圖:
自動配置類的做用,配置注入功能組件自動完成。
a.容許使用@Configuration註解的類
這個比較簡單,若是明確知道須要引入哪一個配置類,直接引入就能夠。
b.容許是實現ImportSelector接口的類
若是並不肯定引入哪一個配置類,須要根據@Import註解所標識的類或者另外一個註解(一般是註解)裏的定義信息選擇配置類的話,用這種方式。
c.Spring會把實現ImportSelector接口的類中的SelectImport方法返回的值注入到Spring容器中(即IOC容器)。這個方法的返回值必須是一個class的全類名的String[]。
比較典型的註解:
好吧,簡單瞭解這個以後,下面來談談重點吧:
@EnableAutoConfiguration剛纔已經貼了一張圖了,點開源碼以後就是
繼續點擊進去,你會發現:
一路點下去,發現AutoConfigurationImportSelector實現了父類接口ImportSelector,而且重寫了父類的selectImports的方法。
在這個方法中,其實主要實現是看configurations這個裏面返回的是什麼東西就好了。
繼續點進去這個方法
繼續點擊進去
這個時候,咱們就豁然開朗了,原來最終咱們是要找「META-INF/spring.factories」這個配置文件啊!
可是這個東西實在哪裏呢,來看看咱們引入的mavenjar包吧。
原來是這個東西,看看裏面是什麼
是否是明白了,***AutoConfiguration,這個不就是咱們上面的註解的形式嗎?
上圖裏面這麼多的xxxAutoConfiguration就是咱們的這麼久得出的結果,最終就是加載這麼多的類的全路徑,而後springboot內部就是實例化這些類並加載到容器裏面,完成springboot應用啓動時的自動配置。
來看看下面這樣圖,他們大神畫的生動的圖,讓人豁然開朗:
藉助於Spring框架原有的一個工具類:SpringFactoriesLoader的支持,@EnableAutoConfiguration能夠智能的自動配置功效才得以大功告成!
SpringFactoriesLoader屬於Spring框架私有的一種擴展方案,其主要功能就是從指定的配置文件META-INF/spring.factories加載配置。
public abstract class SpringFactoriesLoader { //... public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) { ... } public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { .... } }
配合@EnableAutoConfiguration使用的話,它更可能是提供一種配置查找的功能支持,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration做爲查找的Key,獲取對應的一組@Configuration類
上圖就是從SpringBoot的autoconfigure依賴包中的META-INF/spring.factories配置文件中摘錄的一段內容,能夠很好地說明問題。
因此,@EnableAutoConfiguration自動配置的魔法騎士就變成了:從classpath中搜尋全部的META-INF/spring.factories配置文件,並將其中org.springframework.boot.autoconfigure.EnableutoConfiguration對應的配置項經過反射(Java Refletion)實例化爲對應的標註了@Configuration的JavaConfig形式的IoC容器配置類,而後彙總爲一個並加載到IoC容器。
在來探討一個問題:springboot的啓動類其實基本上就兩部分,一部分是spring-boot-starter,另外一部分是spring-boot-autoconfig,starter裏面其實沒有什麼東西,就是依賴了autoconfig。
這麼多的***AutoConfiguration,點進去過去會自動調到對應的啓動類源碼,在啓動類中還有一個配置類***Properties,這個是默認自帶的,例如:這個是activemq的默認配置類(默認的配置類)
在這裏,ActiveMQAutoConfiguration的源碼會關聯這個配置文件,這樣他們就能夠連在一塊兒,最直接的體現就是,咱們在application.properties或者applciation.yml中能夠提示配置文件的屬性
這樣的話,整個啓動類的思路就比較清晰了。
總結:
@ConditionalOnXX 條件判斷註解,經過條件來判斷這個類是否生效!
隨便拿一個啓動器舉例子:
1:springboot啓動的時候會加載大量的自動配置類。spring.factories
2:咱們就須要判斷咱們的類是否在這個裏面,若是不存在,咱們須要手動導入,若是存在,導入啓動器便可。
3:咱們的配置文件(application.yml或者application.properties)之因此能夠自動配置生效:
(1)xxxAutoConfiguation:自動配置類,根據條件@ConditionalOnXX來進行判斷是否生效,若是生效則成功注入bean
(2)xxxProperties:封裝配置文件的相關屬性
4:給容器中自動配置屬性的時候,會經過xxxProperties來獲取某用戶的配置文件中的屬性,若是沒有則使用默認,有則使用本身配置的。
(未完待續........)
本文引用文章聲明:
原文連接:https://blog.csdn.net/neulily2005/article/details/83750027 -------CSDN博主「Mr.甘」
原文連接:https://blog.csdn.net/mapleleafforest/article/details/86623578----------CSDN博主「a maple leaf」
原文連接:http://www.javashuo.com/article/p-conjyivq-ey.html------那啥快看[博客園]
原文連接:http://www.imooc.com/article/275453?block_id=tuijian_wz---Java3y[慕課網]