一.問(wèn)題的引入

          首先我們來(lái)看一個(gè)最簡(jiǎn)單的例子。


          我們先創(chuàng)建一個(gè)SpringBoot的工程,如何創(chuàng)建一個(gè)SpringBoot工程就不說(shuō)了,不會(huì)請(qǐng)自行解決。然后寫(xiě)一個(gè)controller類,通過(guò)請(qǐng)求路徑,返回HelloWorld在瀏覽器頁(yè)面上顯示。

          ? ? ? ??




            上面兩張圖就是程序的一個(gè)整體的結(jié)構(gòu)和運(yùn)行的結(jié)果,那么問(wèn)題來(lái)了,SpringBoot程序中沒(méi)有任何配置,不像Spring框架,寫(xiě)一大堆配置信息在xml文件中,那么程序是怎么將我們這里的Controller類掃描到spring容器中的呢?

          二.原理講解。

          首先第一點(diǎn),我們來(lái)看一下SpringBoot的啟動(dòng)類,
          package com.example.demo; import org.springframework.boot.SpringApplication;
          import org.springframework.boot.autoconfigure.SpringBootApplication;
          @SpringBootApplication public class DemoApplication { public static void
          main(String[] args) { //啟動(dòng)SpringBoot應(yīng)用
          SpringApplication.run(DemoApplication.class, args); } }
            

          其中,我們看到一個(gè)注解@SpringBootApplication
          ,SpringBoot應(yīng)用標(biāo)注在某個(gè)類上說(shuō)明這個(gè)類是SpringBoot的主配置類,SpringBoot就應(yīng)該運(yùn)行這個(gè)類的main方法來(lái)啟動(dòng)SpringBoot應(yīng)用;

          然后我們點(diǎn)進(jìn)去看看這個(gè)注解到底包含了什么,
          @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented
          @Inherited @SpringBootConfiguration @EnableAutoConfiguration
          @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes =
          TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes =
          AutoConfigurationExcludeFilter.class) }) public @interface
          SpringBootApplication {
            

          其中我們需要重點(diǎn)關(guān)注的就是@SpringBootConfiguration、@EnableAutoConfiguration

          下面我們逐個(gè)來(lái)講解:

          @SpringBootConfiguration這個(gè)注解顧名思義,標(biāo)注在某個(gè)類上,這個(gè)類就是SpringBoot的配置類,我們?cè)冱c(diǎn)進(jìn)去看看。
          @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented
          @Configuration
            

          ?

          原來(lái)這個(gè)注解是底層是Spring中的注解@Configuration,而@Configuration注解底層就是一個(gè)@Component,代表一個(gè)容器。

          ?

          ?

          SpringBoot的精髓是在@EnableAutoConfiguration
          這個(gè)注解上,根據(jù)名字,我們可以知道這是一個(gè)自動(dòng)配置類,也就是能夠?qū)崿F(xiàn)一些自動(dòng)配置的功能,那么具體是配置了什么東西呢?

          我們?cè)冱c(diǎn)進(jìn)去看看
          @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented
          @Inherited @AutoConfigurationPackage
          @Import(AutoConfigurationImportSelector.class)
            

          我們看見(jiàn)了和這個(gè)注解有關(guān)聯(lián)的重要的兩個(gè)注解
          @AutoConfigurationPackage,@Import(AutoConfigurationImportSelector.class)
          ,也是分別給大家講解一下。

          1.@AutoConfigurationPackage

          @AutoConfigurationPackage:這是一個(gè)自動(dòng)配置的包,我們來(lái)看下在這個(gè)程序中是配置了哪個(gè)包,點(diǎn)進(jìn)來(lái)
          @Import(AutoConfigurationPackages.Registrar.class)
            

          ?

          再點(diǎn)到Register,我們看到在大概123行的位置,有一段代碼。
          @Override public void registerBeanDefinitions(AnnotationMetadata metadata,
          BeanDefinitionRegistry registry) { register(registry, new
          PackageImport(metadata).getPackageName()); }
            


          我們看到這個(gè)方法器中一個(gè)參數(shù)metadata,代表注解的元信息,然后我們通過(guò)這個(gè)注解的元信息來(lái)獲這個(gè)包名,我們?cè)谶@打個(gè)斷點(diǎn),debug運(yùn)行,可以看見(jiàn)一些元信息的基本內(nèi)容,最主要我們要知道是導(dǎo)入了哪個(gè)包,我們選中
          new PackageImport(metadata).getPackageName(),右鍵計(jì)算一下



          發(fā)現(xiàn)導(dǎo)入的包就是我們項(xiàng)目的根目錄,假如我們新建一個(gè)包叫com.controller,在里面寫(xiě)一個(gè)controller類,大家可以運(yùn)行的試一下是否能成功呢。

          ?

          2.@Import(AutoConfigurationImportSelector.class)

          ? ? ?@Import(AutoConfigurationImportSelector.class):
          這個(gè)注解代表的是一個(gè)自動(dòng)配置的選擇器,那么要導(dǎo)入哪些組件的選擇器呢?

          我們點(diǎn)進(jìn)去,看到非常重要的一段。
          protected AutoConfigurationEntry
          getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
          AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) {
          return EMPTY_ENTRY; } AnnotationAttributes attributes =
          getAttributes(annotationMetadata); List<String> configurations =
          getCandidateConfigurations(annotationMetadata, attributes); configurations =
          removeDuplicates(configurations); Set<String> exclusions =
          getExclusions(annotationMetadata, attributes);
          checkExcludedClasses(configurations, exclusions);
          configurations.removeAll(exclusions); configurations = filter(configurations,
          autoConfigurationMetadata); fireAutoConfigurationImportEvents(configurations,
          exclusions); return new AutoConfigurationEntry(configurations, exclusions); }
            

          ?這里我們獲得到了一個(gè)configurations 的list集合,我們打個(gè)斷點(diǎn)看看這個(gè)集合中到底給我們裝了些什么東西。



          我們發(fā)現(xiàn)這個(gè)configurations 里面裝配了124個(gè)自動(dòng)配置類,原來(lái)我們沒(méi)有配置的一些信息,都通過(guò)SpringBoot的自動(dòng)配置類給我配置好了。

          那么我還想知道這些類SpringBoot程序給我們放到哪了呢,我們看到
          getCandidateConfigurations(annotationMetadata, attributes);

          點(diǎn)進(jìn)去,我們看到:
          List<String> configurations =
          SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass()
            

          ?

          那么再點(diǎn)進(jìn)去我們看看到底加載的工廠名稱是啥,
          try { Enumeration<URL> urls = (classLoader != null ?
          classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
          ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); 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()) { String factoryTypeName = ((String)
          entry.getKey()).trim(); for (String factoryImplementationName :
          StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
          result.add(factoryTypeName, factoryImplementationName.trim()); } } }
            

          我們看到其中類加載器給我們獲取了資源,我們點(diǎn)進(jìn)去,

          點(diǎn)了這么多次,終于找到我們想要的答案了?。。?br>public static final String FACTORIES_RESOURCE_LOCATION =
          "META-INF/spring.factories";
            

          ?

          原來(lái)這些自動(dòng)配置類都在類路徑下的"META-INF/spring.factories"



          還有下面的autoconfigure包中的內(nèi)容,我們也看看




          這里面我們所有所用到的配置類全部由SpringBoot給我們配置了,所以我們知道SpringBoot表面上是零配置的,其實(shí)底層都給我們封裝好了,也是方便我們程序員進(jìn)行開(kāi)發(fā)。

          那么有些人肯定又有疑惑,SpringBoot怎么知道給我們自動(dòng)配置哪些類呢?

          欲知后事如何,請(qǐng)關(guān)注一下作者,純手打碼字不易,也是希望和大家多多交流,一起學(xué)習(xí),謝謝!



          ?

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點(diǎn)信息
          問(wèn)題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                亚洲日本中文字幕 | 日日摸夜夜添夜夜添国产精品 | 殴美成人精品 | 久久中文网| 美女三级视频 |