關於spring boot項目配置文件的一些想法


一、springboot項目中有兩種配置文件

springboot項目中有兩種配置文件 bootstrap 和 application

bootstrap是應用程序的父上下文,由父Spring ApplicationContext加載。所以加載順序優先於application。

bootstrap 里面的屬性不能被覆蓋。

應用場景

  • bootstrap
  1. 使用 Spring Cloud Config 配置中心時,這時需要在bootstrap 配置文件中添加連接到配置中心的配置屬性,來加載外部配置中心的配置信息
  2. 一些固定的不能被覆蓋的屬性
  3. 一些加密/解密的場景
  • application
  1. 主要用於 Spring Boot 項目的自動化配置

二、配置文件的使用

1、配置文件的書寫小技巧

spring:
  application:
    name: @artifactId@
  cloud:
    nacos:
      discovery:
        server-addr: nacoshost:8848
      config:
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        file-extension: yml
        shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
  autoconfigure:
    exclude: org.springframework.cloud.gateway.config.GatewayAutoConfiguration,org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration
  profiles:
    active: @profiles.active@

這段是配置文件內容:@artifactId@ 可以定位到pom 文件中的 <artifactId>pipe-server</artifactId>

          @profiles.active@ 可以定位到pom文件中的 <profiles.active>test</profiles.active>

server-addr: ${spring.cloud.nacos.discovery.server-addr}
這種寫法 ${}定位的值就是本yml文件:server-addr: nacoshost:8848 這個地方

2、外部配置文件的引用以及多配置文件切換

  把外部鏈接地址放在bootstrap 文件里面 然后去讀取文件 外部文件或者在服務器上,或者在git 通過nacos、spring cloud config、apollo 等等去找到外部文件然后讀取。

1.多配置文件

  profile是Spring對不同環境提供不同配置功能的支持,可以通過激活不同的環境版本,實現快速切換環境;在主配置文件編寫的時候,文件名可以是 application-{profile}.properties/yml , 用來指定多個環境版本;

  例如:application-test.properties 代表測試環境配置    application-dev.properties 代表開發環境配置,但是Springboot並不會直接啟動這些配置文件,它默認使用application.properties主配置文件;

  我們需要通過一個配置來選擇需要激活的環境:在bootstrap中使用:spring.profiles.active=dev

3、讀取配置文件內容

寫個yml文件:

anything:
  isok: true
  sout: im.peizhi.wenjian
/*
@ConfigurationProperties作用:
將配置文件中配置的每一個屬性的值,映射到這個組件中;
告訴SpringBoot將本類中的所有屬性和配置文件中相關的配置進行綁定
參數 prefix = “person” : 將配置文件中的person下面的所有屬性一一對應

只有這個組件是容器中的組件,才能使用容器提供的@ConfigurationProperties功能
*/
@Component //注冊bean
@ConfigurationProperties(prefix = "anything")
public class Anything{
  private Boolean isok;
  private String sout ; }

除了@ConfigurationProperties以外還可以使用@Value進行讀取:

@Component //注冊bean
public class Person {
    //直接使用@value
   @Value("${anything.isok}") //從配置文件中取值  
  private Boolean isok;

@ConfigurationProperties是支持松散綁定的 松散綁定:比如我的yml中寫的last-name,這個和lastName是一樣的, - 后面跟着的字母默認是大寫的。這就是松散綁定 ,@Value 不支持

@Value的其他使用方法:應該可以猜的看懂吧 不贅述了

@Component("role2")
public class Role2 {
//賦值long型
@Value("#{2}")
private Long id;
//字符串賦值
@Value("#{'role_name_2'}")
private String roleName;
//字符串賦值
@Value("#{'note_2'}")
private String note;
}
@Component(
"elBean") public class ElBean { //通過beanName獲取bean,然后注入 @Value("#{role2}") private Role2 role2; //獲取bean的屬性id @Value("#{role2.id}") private Long id; //調用bean的getNote方法,獲取角色名稱 // @Value("#{role.getNote().toString()}") @Value("#{role2.getNote()?.toString()}") private String note; @Value("#{T(Math).PI}") private double pi; @Value("#{T(Math).random()}") private double random; @Value("#{role.id+1}") private int num; }

@PropertySource :加載指定的配置文件;

@PropertySource(value = "classpath:bootstrap.yml")
@Component //注冊bean
public class Anything{
    @Value("${anything.isok}")
    private String name;
}

三、自動自動配置的原理

1.SpringBoot啟動的時候加載主配置類,開啟自動配置功能@EnableAutoConfig

2.@EnableAutoConfig作用:

  • 利用EnableAutoConfigurationImportSelector給容器中導入一些組件,導入了哪些組件呢?
  • 可以查看這個類selectImports()方法的內容,他返回了一個  autoConfigurationEntry , 來自  this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); 這個方法。我們繼續跟蹤;
  • 這個方法中有一個值 : List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); 叫做獲取候選的配置 , 我們點擊去繼續跟蹤;
  • protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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; }
     

     這里里面有一個 SpringFactoriesLoader.loadFactoryNames() ,我們繼續進去看 , 它又調用了  loadSpringFactories 方法;繼續跟蹤。發現它去獲得了一個資源文件:"META-INF/spring.factories"

  • Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
     

     繼續閱讀源碼 , 它將讀取到的資源封裝在url中,然后遍歷url , 將這些url文件封裝在Properties文件中;最后返回封裝好的結果;他的那個ClassLoader參數,我們追蹤回去,看到他就是 EnableAutoConfiguration ;

  • 說明了這個邏輯就是 從properties中獲取到EnableAutoConfiguration.class類(類名)對應的值,然后把他們添加在容器中 

  • 總結一句話就是:將類路徑下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;每一個 xxxAutoConfiguration類都是容器中的一個組件,最后都加入到容器中;用他們來做自動配置;

3.每一個自動配置類可以進行自動配置功能;

4.我們HttpEncodingAutoConfiguration(Http編碼自動配置)為例解釋自動配置原理;

所有在配置文件中能配置的屬性都是在xxxxProperties類中封裝者‘;配置文件能配置什么就可以參照某個功能對應的這個屬性類

@ConfigurationProperties( prefix = "spring.http" ) //從配置文件中獲取指定的值和bean的屬性進行綁定 在一次工作中我的書寫是這樣的(prefix = "tlyh.restUrl")報錯格式不規范 應該改為:tlyh.rest-url
public class HttpProperties {
    private boolean logRequestDetails;
    private final HttpProperties.Encoding encoding = new HttpProperties.Encoding();

    public HttpProperties() {
    }

    public boolean isLogRequestDetails() {
        return this.logRequestDetails;
    }

    public void setLogRequestDetails(boolean logRequestDetails) {
        this.logRequestDetails = logRequestDetails;
    }

    public HttpProperties.Encoding getEncoding() {
        return this.encoding;
    }

    public static class Encoding {
        public static final Charset DEFAULT_CHARSET;
        private Charset charset;
        private Boolean force;
        private Boolean forceRequest;
        private Boolean forceResponse;
        private Map<Locale, Charset> mapping;
    }
}

5. 下面是自己寫的HttpEncodingAutoConfiguration組件

@Configuration //表示這是一個配置類,以前編寫的配置文件一樣,也可以給容器中添加組件 //啟動指定類的ConfigurationProperties功能; //進入這個HttpProperties查看,將配置文件中對應的值和HttpProperties綁定起來; //並把HttpProperties加入到ioc容器中 @EnableConfigurationProperties({HttpProperties.class}) //Spring底層@Conditional注解 //根據不同的條件判斷,如果滿足指定的條件,整個配置類里面的配置就會生效; //這里的意思就是判斷當前應用是否是web應用,如果是,當前配置類生效 @ConditionalOnWebApplication( type = Type.SERVLET ) //判斷當前項目有沒有這個類CharacterEncodingFilter;SpringMVC中進行亂碼解決的過濾器; @ConditionalOnClass({CharacterEncodingFilter.class}) //判斷配置文件中是否存在某個配置:spring.http.encoding.enabled; //如果不存在,判斷也是成立的 //即使我們配置文件中不配置pring.http.encoding.enabled=true,也是默認生效的; @ConditionalOnProperty( prefix = "spring.http.encoding", value = {"enabled"}, matchIfMissing = true ) public class HttpEncodingAutoConfiguration { //他已經和SpringBoot的配置文件映射了 private final Encoding properties; //只有一個有參構造器的情況下,參數的值就會從容器中拿 public HttpEncodingAutoConfiguration(HttpProperties properties) { this.properties = properties.getEncoding(); } //給容器中添加一個組件,這個組件的某些值需要從properties中獲取  @Bean @ConditionalOnMissingBean //判斷容器沒有這個組件? public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE)); return filter; } } 

一句話總結 : 根據當前不同的條件判斷,決定這個配置類是否生效!

 一但這個配置類生效;這個配置類就會給容器中添加各種組件;這些組件的屬性是從對應的properties類中獲取的,這些類里面的每一個屬性又是和配置文件綁定的;

 
        

這就是自動裝配的原理!

 
        

精髓:

 
        

1)、SpringBoot啟動會加載大量的自動配置類

 
        

2)、我們看我們需要的功能有沒有在SpringBoot默認寫好的自動配置類當中;

 
        

3)、我們再來看這個自動配置類中到底配置了哪些組件;(只要我們要用的組件存在在其中,我們就不需要再手動配置了)

 
        

4)、給容器中自動配置類添加組件的時候,會從properties類中獲取某些屬性。我們只需要在配置文件中指定這些屬性的值即可;

 
        

xxxxAutoConfigurartion:自動配置類;給容器中添加組件

 
        

xxxxProperties:封裝配置文件中相關屬性;

@Conditional

了解完自動裝配的原理后,我們來關注一個細節問題 ,自動配置類必須在一定的條件下才能生效;

@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必須是@Conditional指定的條件成立,才給容器中添加組件,配置配里面的所有內容才生效;

那么多的自動配置類,必須在一定的條件下才能生效;也就是說,我們加載了這么多的配置類,但不是所有的都生效了。

我們怎么知道哪些自動配置類生效;我們可以通過啟用 debug=true屬性;來讓控制台打印自動配置報告,這樣我們就可以很方便的知道哪些自動配置類生效;

#開啟springboot的調試類 debug=true
 


免責聲明!

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



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