Springboot筆記<1>版本控制器、場景啟動器與自動配置原理


springboot版本控制器

SpringBoot應用的pom.xml中引入了一個父項目parent:spring-boot-starter-parent,spring-boot-starter-parent的父項目為spring-boot-dependenciesspring-boot-dependencies相當於SpringBoot的版本仲裁中心,其中有個properties標簽指定了一些依賴的版本:解決了一些版本沖突的問題,有了它我們在導入依賴時默認不需要寫版本號,但是沒有在此處聲明版本號的依賴依然需要寫明版本。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.1</version>
    <relativePath/> 
</parent>


<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-dependencies</artifactId>
  <version>2.6.1</version>
</parent>


<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.1</version>
<packaging>pom</packaging>

properties標簽:

<properties>
  <activemq.version>5.16.3</activemq.version>
  <antlr2.version>2.7.7</antlr2.version>
  <appengine-sdk.version>1.9.92</appengine-sdk.version>
  <artemis.version>2.19.0</artemis.version>
  <aspectj.version>1.9.7</aspectj.version>
  <assertj.version>3.21.0</assertj.version>
  <atomikos.version>4.0.6</atomikos.version>
  <awaitility.version>4.1.1</awaitility.version>
  <build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version>
  <byte-buddy.version>1.11.22</byte-buddy.version>
  <caffeine.version>2.9.2</caffeine.version>
  etc……
  <properties>

版本仲裁:

1、引入依賴默認都可以不寫版本
2、引入非版本仲裁的jar,要寫版本號。

修改默認版本號:

查看spring-boot-dependencies里面規定當前依賴的版本用的 key。

1、引入依賴時直接寫上版本號

2、在當前項目里面重寫配置

    <properties>
        <mysql.version>5.1.43</mysql.version>
    </properties>

這兩種方法其實都是利用maven提供的特性,就近優先原則,就是在當前項目中已經配置了某個依賴的版本號我就使用其版本號,如果當前項目中沒有配置其版本號,我就去其父項目中找其版本號。

版本依賴關系

  • ctrl + shift + alt + U:以圖的方式顯示項目中依賴之間的關系。

springboot場景啟動器

spring-boot-starter場景啟動器:

   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.6.1</version>
      <scope>compile</scope>
   </dependency>

springboot的各種各樣的 starters,有官方提供的,也有第三方開源出來。starter是springBoot的一個重要部分。通過starter,我們能夠快速的引入一個功能,而無需額外的配置。同時starter一般還會給我提供預留的自定配置選項,我們只需要在application.properties中設置相關參數,就可以實現配置的個性化。

springboot場景:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>2.6.1</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-activemq</artifactId>
  <version>2.6.1</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
  <version>2.6.1</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-amqp</artifactId>
  <version>2.6.1</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
  <version>2.6.1</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-artemis</artifactId>
  <version>2.6.1</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-batch</artifactId>
  <version>2.6.1</version>
</dependency>

自動配置

  • 自動配好Tomcat

    ​ 引入Tomcat依賴,配置Tomcat

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.3.4.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  • 自動配好SpringMVC

    ​ 引入SpringMVC全套組件,自動配好SpringMVC常用組件(功能)

  • 自動配好Web常見功能,如:字符編碼問題

  • SpringBoot幫我們配置好了所有web開發的常見場景

  • 默認的包結構

    ​ 主程序所在包及其下面的所有子包里面的組件都會被默認掃描進來,無需以前的包掃描配置想要改變掃描路徑,@SpringBootApplication(scanBasePackages="###.###")或者@ComponentScan 指定掃描路徑

@SpringBootApplication
等同於
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("包路徑")
  • 各種配置擁有默認值

    ​ 默認配置最終都是映射到某個類上,如:MultipartProperties

    ​ 配置文件的值最終會綁定每個類上,這個類會在容器中創建對象

  • 按需加載所有自動配置項

    ​ 非常多的starter,引入了哪些場景這個場景的自動配置才會開啟,SpringBoot所有的自動配置功能都在 spring-boot-autoconfigure 包里面

springboot自動配置原理

@SpringBootApplication

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
  • @SpringBootConfiguration:標記當前類為配置類

  • @EnableAutoConfiguration:開啟自動配置

  • @ComponentScan:掃描主類所在的同級包以及下級包里的Bean

    關鍵是@EnableAutoConfiguration

@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

   /**
    * Environment property that can be used to override when auto-configuration is
    * enabled.
    */
   String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

   /**
    * Exclude specific auto-configuration classes such that they will never be applied.
    * @return the classes to exclude
    */
   Class<?>[] exclude() default {};

   /**
    * Exclude specific auto-configuration class names such that they will never be
    * applied.
    * @return the class names to exclude
    * @since 1.3.0
    */
   String[] excludeName() default {};

}
@AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class)  //給容器中導入一個組件
public @interface AutoConfigurationPackage {}

@AutoConfigurationPackage利用Registrar給容器中導入一系列組件

@Import(AutoConfigurationImportSelector.class)

@EnableAutoConfiguration其中最關鍵的要屬@Import(AutoConfigurationImportSelector.class),借助AutoConfigurationImportSelector,@EnableAutoConfiguration可以幫助SpringBoot應用將所有符合條件的@Configuration配置都加載到當前SpringBoot創建並使用IOC容器。

AutoConfigurationImportSelector中方法的作用:

1、利用getAutoConfigurationEntry(annotationMetadata);給容器中批量導入一些組件
2、調用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)獲取到所有需要導入到容器中的配置類
3、利用工廠加載 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的組件
4、從META-INF/spring.factories位置來加載一個文件。默認掃描我們當前系統里面所有META-INF/spring.factories位置的文件
spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

在AutoConfigurationImportSelector類中可以看到通過 SpringFactoriesLoader(Spring框架原有的一個工具類).loadFactoryNames()
把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一個xxxAutoConfiguration文件都加載到容器中,spring.factories文件里每一個xxxAutoConfiguration文件一般都會有下面的條件注解:

@ConditionalOnClass : classpath中存在該類時起效
@ConditionalOnMissingClass : classpath中不存在該類時起效
@ConditionalOnBean : DI容器中存在該類型Bean時起效
@ConditionalOnMissingBean : DI容器中不存在該類型Bean時起效
@ConditionalOnSingleCandidate : DI容器中該類型Bean只有一個或@Primary的只有一個時起效
@ConditionalOnExpression : SpEL表達式結果為true時
@ConditionalOnProperty : 參數設置或者值一致時起效
@ConditionalOnResource : 指定的文件存在時起效
@ConditionalOnJndi : 指定的JNDI存在時起效
@ConditionalOnJava : 指定的Java版本存在時起效
@ConditionalOnWebApplication : Web應用環境下起效
@ConditionalOnNotWebApplication : 非Web應用環境下起效

AutoConfigurationImportSelector中的方法getCandidateConfigurations,得到待配置的class的類名集合,這個集合就是所有需要進行自動配置的類,而是是否配置的關鍵在於META-INF/spring.factories文件中是否存在該配置信息。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
   List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
         getBeanClassLoader());
   Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
         + "are using a custom packaging, make sure that file is correct.");
   return configurations;
}

所有需要配置的類全路徑都在文件\spring-boot-autoconfigure\2.6.1\spring-boot-autoconfigure-2.6.1.jar!\META-INF\spring.factories中,每行一個配置,多個類名逗號分隔,而\表示忽略換行。(以下截取部分)

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.autoconfigure.integration.IntegrationPropertiesEnvironmentPostProcessor

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
……

總結:

  • SpringBoot先加載所有的自動配置類 xxxxxAutoConfiguration

  • 每個自動配置類按照條件進行生效,默認都會綁定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件進行了綁定

  • 生效的配置類就會給容器中裝配很多組件

  • 只要容器中有這些組件,相當於這些功能就有了

  • 定制化配置

    • 用戶直接自己@Bean替換底層的組件
    • 用戶去看這個組件是獲取的配置文件什么值就去修改。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM