Spring Boot 官方文檔學習(二)特點


一、SpringApplication

banner,就是啟動時輸出的信息,可以在classpath下添加 banner.txt,或者設置 banner.location 來指向特定的文件。(默認編碼utf-8,或者通過banner.charset指定)
除了txt,你還可以使用 banner.gif (jpg / png),或者設定 banner.imgage.location。
下面是默認的banner(忽略吧,沒意義的東西):

banner變量,只有應用相關的信息,略,見pdf。

還可以使用通過 SpringApplication.setBanner(…) 來設置。通過實現 org.springframework.boot.Banner 接口,可以實現自己的 printBanner() 。
通過設置 spring.main.banner-mode 來決定是否在  System.out  (console) 上顯示banner。使用配置的logger (log)或者全不用 (off)。 
輸出的banner會被注冊成一個單例的bean,名字springBootBanner。
 
 
如果,你想創建一個分層次的ApplicationContext (多個context,有父子關系),可以使用  SpringApplicationBuilder 。它可以讓你鏈式調用方法,並且設置父子關系。如下:
new SpringApplicationBuilder()
    .bannerMode(Banner.Mode.OFF)
    .sources(Parent.class)
    .child(Application.class)
    .run(args);
SpringApplicationBuilder使用起來有一些限制,詳見javadoc。
 
 
Application事件和監聽器
除了Spring框架的事件(如ContextRefreshedEvent)之外,SpringApplication還提供了一些額外的事件。
但是,有些事件是在ApplicationContext創建之前,所以無法通過@Bean形式注冊監聽器。可以通過SpringApplication.addListeners(...) 或者 SpringApplicaitonBuilder.listeners(...) 來注冊。
另外,如果想以與application創建形式無關的方式來注冊listeners,可以這樣做:創建一個 META-INF/spring.factories 文件。內容如下:
org.springframework.context.ApplicationListener=com.example.project.MyListener
多個監聽器,應該用逗號連接吧???
 
Application Events,以下面的順序發送:
  1. ApplicationStartedEvent 應用啟動時發送,是除了注冊監聽器和初始化之外最早的。
  2. ApplicationEnvironmentPreparedEvent 創建context之前,已知道context需要使用的Environment時。
  3. ApplicationPreparedEvent 發生在context刷新之前,但在bean 定義加載之后。
  4. ApplicationReadyEvent 發生在刷新和任何相關回調被處理之后,表明應用已准備好響應請求了。
  5. ApplicationFailedEvent 發生在啟動期間發生異常時。
沒必要使用這些事件,但是了解一下還是挺有用的。Spring Boot內部使用這些事件來處理很多任務。
 
Web 環境
SpringApplication 會試圖創建正確的 ApplicationContext。默認的,使用 AnnotationConfigApplicationContext 或者 AnnotationConfigEmbeddedWebApplicationContext ,這取決於是否web應用。
可以使用覆蓋 setWebEnvironment(boolean webEnvironment) 默認設置。
也可以使用 setApplicationContextClass(…) 來控制 ApplicationContext 的類型。
注意:當在JUnit環境下使用SpringApplication時,通常需要設置 setWebEnvironment(false) 。
 
訪問應用的參數
如何訪問傳遞給SpringApplication.run(...) 的參數?
你可以注入一個 org.springframework.boot.ApplicationArguments bean。這是一個接口,提供了 String[] 和 option/non-option 參數形式。
import org.springframework.boot.*
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*
@Component
public class MyBean {
    @Autowired
    public MyBean(ApplicationArguments args) {
        boolean debug = args.containsOption("debug");
        List<String> files = args.getNonOptionArgs();
        // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
    }
}

 

注意,Spring Boot還會在Spring Environment中注冊一個 CommandLinePropertySource 。它可以讓你使用 @Value 注解注入application argument。
就是,如果有argument --larry.name=larry,那么可以使用@Value("${larry.name}"}String larryName;
 

ApplicationRunner or CommandLineRunner

如果想在SpringApplication啟動后執行一些特定的代碼,可以讓這些代碼實現  ApplicationRunner  or CommandLineRunner 接口。二者都提供了一個run(),可以在SpringApplication.run(...) 完成之前被調用。
區別: CommandLineRunner 只提供對傳遞參數的默認訪問形式 String[],而  ApplicationRunner 則使用了上面提到的 ApplicationArguments 接口。
import org.springframework.boot.*
import org.springframework.stereotype.*
@Component
public class MyBean implements CommandLineRunner {
    public void run(String... args) {
        // Do something...
    }
}
如果,定義了多個  CommandLineRunner  or ApplicationRunner beans,那么可以通過實現 org.springframework.core.Ordered 接口或使用 org.springframework.core.annotation.Order 注解來控制加載順序。
 
Application exit
每一個 SpringApplication 都注冊了一個shutdown hook with JVM,以確保 ApplicationContext 順利的關閉。所有的Spring生命周期中的回調(如 DisposableBean 接口,或者 @PreDestroy 注解)都可以使用。
另外,如果想在應用退出時返回特定的exit code,那beans可以實現 org.springframework.boot.ExitCodeGenerator 接口。
個人經驗:同樣可以使用@Order控制順序,只不過相反。
個人經驗:使用@Order控制的順序,不能打破大的順序。例如上面(ApplicationRunner or CommandLineRunner)的順序,永遠在SpringApplication啟動完成之前調用。

Admin features(略)

 

Externalized Configuration(需要認真看看)

外來配置?就是說,通過設定這些配置,可以在不同的工作環境下運行相同的代碼達到相同的目的。
Spring Boot支持的:properties文件、yaml文件、environment 變量、命令行參數。
然后,可以通過 @Value 注解注入到bean中,或者通過Spring 的 Environment 訪問,或者通過 @ConfigurationProperties  綁定到結構化對象中。
個人經驗:@Value 的工作是在SpringApplication啟動完成 之后進行的,在此之前值為null。
注意:不同方式的配置的優先級不一樣。基本上,除了測試情況外,命令行參數優先級最高。尤其要注意指定profile下的優先級比默認的高。具體如下:
  1. @TestPropertySource annotations on your tests.
  2. Command line arguments.
  3. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)
  4. ServletConfig init parameters.
  5. ServletContext init parameters.
  6. JNDI attributes from java:comp/env.
  7. Java System properties (System.getProperties()).
  8. OS environment variables.
  9. A RandomValuePropertySource that only has properties in random.*.
  10. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
  11. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
  12. Application properties outside of your packaged jar (application.properties and YAML variants).
  13. Application properties packaged inside your jar (application.properties and YAML variants).
  14. @PropertySource annotations on your @Configuration classes.
  15. Default properties (specified using SpringApplication.setDefaultProperties).
 

 Configuring random values

RandomValuePropertySource 用於注入隨機數值,它可以生成int、long、uuid 或者 字符串。如下:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

 

Accessing command line properties

默認,SpringApplication會將任何命令行參數(以--開頭,如--server.port=8900)轉成一個property,並添加到Spring Environment中。
再次強調:命令行參數的優先級最高。
如果不想添加到Spring Environment中,你可以禁用它們: SpringApplication.setAddCommandLineProperties(false) 。
 
關於application.properties文件
SpringApplication默認從以下地址加載,並添加到Spring Environment 中。
/config
/
classpath/
classpath/config
注意,優先級從上往下依次降低。
如果不想使用默認的名字,可以自行指定(兩種方式):
java -jar myproject.jar --spring.config.name=myproject
java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
注意,默認的加載地址 永遠有效,但可以添加新的,且新的地址的優先級更高。
注意,多數系統的環境變量不允許使用點分隔的鍵名,可以使用下划線代替。如: SPRING_CONFIG_NAME 代替 spring.config.name 。
另外,如果在容器中執行,還可以使用JNDI properties或者 Servlet Context初始化參數。
 
Profile-specific properties
在 application.properties 之外,還會加載 application-{profile}.properties 。由於 Environment 提供了一個默認的profile,所以,默認還會加載 application-default.properties 。
奇怪,這什么意思:
  • If you have specified any files in spring.config.location, profile-specific variants of those files will not be considered. Use directories in `spring.config.location` if you also want to also use profile-specific properties.
 
properties中的占位符
application.properties 中的值是按順序加載到已有的 Environment 中,所以,后面的值可以使用前面的值,使用方法就是占位符。如下:
  1. app.name=MyApp
  2. app.description=${app.name} is a Spring Boot application
可以利用該技術創建短的變量?
 
YAML是JSON的超集!(略)
classpath中只要有SnakeYAML 庫,SpringApplication就可以自動支持YAML。
而,Starters默認就含有SnakeYAML 庫。
 
類型安全的Configuration Properties
這里的意思是說,通過Java類來確保類型安全,但 值還是要在YAML中提供!!!
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
    private String username;
    private InetAddress remoteAddress;
    // ... getters and setters
}
那么,@Value("${property}")  和@ConfigurationProperties 的區別? 暫略。
注意: 通過 @ConfigurationProperties 類進行的properties設置,需要在 @Configuration 類上開啟 @EnableConfigurationProperties 注解才行,而且,需要手動添加 @ConfigurationProperties  類,如下:
@Configuration
@EnableConfigurationProperties(ConnectionProperties.class)
public class MyConfiguration {
}

 

需要注意的是, @ConfigurationProperties 類對應的bean有一個約定好的名字:  <prefix>-<fqn> 。fqn是full qualified name。
前面的例子,對應的名字是: connection-com.example.ConnectionProperties ,這里假定它在包 com.example 中。
但是,@ConfigurationProperties 類對應的bean還有一個默認的名字!!!只是,不建議在environment之外使用而已。
 
除了上面的紅字部分,由於 @EnableConfigurationProperties 注解 會被自動應用到項目中,所以,只要確保 @ConfigurationProperties 類 是一個bean(即@Component),就會被自動添加到 Environment 。如下:
@Component //確保是一個bean即可!
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
    // ... getters and setters of username and remoteAddress, and so on
}
這種形式的配置可以和YAML配置完美的配合。為什么要配合? 因為上面只是類型安全,沒有值!!!
# application.yml
connection:
    username: admin
    remoteAddress: 192.168.1.1
# additional configuration as required
 
個人經驗:奇怪,為什么STS提示我在pom中添加spring-boot-starter-configxxxxx ?

提示:使用 @ConfigurationProperties,還可以生成meta-data文件,以供IDE使用。
 
第三方配置?
@ConfigurationProperties 還可以用於 @Bean 方法上。如下:
@ConfigurationProperties(prefix = "foo")
@Bean
public FooComponent fooComponent() {
    ...
}
這樣,就是給bean加一個前綴,這個bean就可被用作ConfigurationProperties了!!!! 貌似也沒別的了,一個bean而已。
 
靈活的綁定:是指對名字的匹配
例如:
@ConfigurationProperties(prefix="person")
public class OwnerProperties {
    private String firstName;
    public String getFirstName() {
        return this.firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}

 

這里的 firstName 可以綁定如下內容:
person.firstName Standard camel case syntax.
person.first-name Dashed notation, recommended for use in.properties and .yml files.
person.first_name Underscore notation, alternative format for use in .properties and .yml files.
PERSON_FIRST_NAME Upper case format. Recommended when using a system environment variables.

Properties conversion,轉換,類似SpringMVC的轉換
如果要自定義類型轉換,三種方式:創建一個 ConversionService bean,或者創建一個 property editors(通過 CustomEditorConfigurer bean),或者創建一個 Converters (@ConfigurationPropertiesBinding)。
注意:這個bean在應用早期被調用,所以,注意限制它的依賴!
 
@ConfigurationProperties validation
Spring Boot默認使用JSR-303去校驗,所以可以使用JSR-303的注解。如下:
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
    @NotNull
    private InetAddress remoteAddress;
    // ... getters and setters
}
如果有嵌套屬性,需要使用@Valid來觸發校驗。如:
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
    @NotNull
    @Valid
    private RemoteAddress remoteAddress;
    // ... getters and setters
    public static class RemoteAddress {
        @NotEmpty
        public String hostname;
        // ... getters and setters
    }
}

 

也可以使用自定的Spring Validator,bean id是 configurationPropertiesValidator 即可。
注意: spring-boot-actuator 模塊有一個端點,對外暴露了所有的 @ConfigurationProperties beans。瀏覽器中訪問 /configprops 即可。也可以使用相應的JMX端點???
個人經驗:其實還有很多地址,詳見啟動信息。如下:

 
 
@Value("${property}")  和@ConfigurationProperties 的區別
@Value 是core container的feature。不支持靈活綁定,不支持Meta-data。但支持spELl。
@ConfigurationProperties 則支持靈活綁定,支持Meta-data。但不支持spELl。
官方指導里 推薦使用后者
 
Profiles
@Profile 可以用於 @Component 或 @Configuration 。
使用  spring.profiles.active Environment property 來指定運行時的 profile 。如:
#application.properties
spring.profiles.active=dev,hsqldb
#command line argument
--spring.profiles.active=dev,hsqldb
有時候,添加profile 比替換profile 更有用。
spring.profiles.include property 可以做到無條件的添加profile。
SpringApplication也提供了API來添加profile: setAdditionalProfiles() 。
還可以使用 Spring的 ConfigurableEnvironment 接口(實驗了下,太麻煩,不建議使用)。
問題:@Profile在類上和在方法上,是怎么結合的???怎么出問題了。
 
 
Logging
Spring Boot 使用JCL接口,但未指定實現。默認的實現包括JUL、Log4j2、Logback。均已設置console輸出。
如果使用Starter模塊,則使用Logback
Log Level:ERROR, WARN, INFO, DEBUG or TRACE
注意,Logback沒有FATAL,如果設置了FATAL,會被映射成ERROR。
開啟debug模式:--debug,或者在 application.properties:debug=true。
注意,是debug模式,不是DEBUG Level。
 
彩色輸出
終端支持ANSI才行,不過現在還有不支持的嗎?
需要設置 spring.output.ansi.enabled 。
STS中以Spring Boot Application啟動時,應該默認設置了。
問題是,為什么我直接以Java Application啟動就不行?-- 因為沒有設置顏色。囧~~
 
File output
默認Log只會ouput到console。如果想輸出到File,應該設置  logging.file 或者 logging.path  property 。

注意:輸出文件大小到達10 Mb時,會重新開始?
注意:logging系統是在應用的早期初始化的,所以,不能在通過 @PropertySource 加載的文件中配置。
注意:logging properties 與實際的logging系統無關,所以,Spring Boot不會管理具體的配置文件,如 logback.configurationFile 或 logback.xml 。  會加載,會執行,但與Spring Boot無關,是logging系統自己的東西
 
Log Levels
所有Spring Boot支持的logging系統,都可以在Spring Environment 中設置(如application.properties),格式:logging.level.*=LEVEL。
其中,LEVEL可以是TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF。
root logger可以使用 logging.level.root 設置。如下:
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

 

 
自定義log配置
可以使用不同的logging系統, 只要在classpath中添加相應的jars即可。更進一步,還可以在classpath提供一個相應的配置文件,或者在一個指定的位置(需要使用 logging.config 來指定)。
也可以使用一個特定的logging系統,使用 org.springframework.boot.logging.LoggingSystem  來指定,注意,該鍵對應的值是具體logging實現的全路徑,如為none,則默認完全禁用Spring Boot的logging配置。
再次提醒:logging系統初始化較早,不能使用 @Configuration 里的 @PropertySources 來控制。
 
根據不同的logging實現,加載不同的配置文件。如下:
Logback logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml

JDK (Java Util Logging)

logging.properties
注意: 官方建議使用 -spring的文件名,否則Spring不能完全控制log初始化(因為初始化太早)。
警告:直接運行fat jar時,JUL會有問題,建議避免使用它。
 
個人問題: Spring Environment 和 System properties 什么關系?為什么書上說一些properties會從前者傳到后者,以幫助自定義?
Spring Environment System Property Comments
logging.exception-conversion-word LOG_EXCEPTION_CONVERSION_WORD The conversion word that’s used when logging exceptions.異常?例外?
logging.file LOG_FILE Used in default log configuration if defined.
logging.path LOG_PATH Used in default log configuration if defined.
logging.pattern.console CONSOLE_LOG_PATTERN The log pattern to use on the console (stdout). (Only supported with the default logback setup.) 僅支持默認logback設置。
logging.pattern.file FILE_LOG_PATTERN The log pattern to use in a file (if LOG_FILE enabled). (Only supported with the default logback setup.) 僅支持默認logback設置。
logging.pattern.level LOG_LEVEL_PATTERN The format to use to render the log level (default %5p).(Only supported with the default logback setup.)  僅支持默認logback設置。
PID PID The current process ID (discovered if possible and when not already defined as an OS environment variable).
注意,如果要使用占位符,應該使用Spring Boot的,而非Spring的。
例子就是Logback的分隔符,應該用“:”,而非“:-”。
提示:SB包含了Logback的大量擴展,用於協助配置。可以在 logback-spring.xml 中使用它們。
注意: 不能在  logback.xml  中使用這些擴展,因為它被加載的太早了
 
Profile-specific Configuration (logging)
可以在 <configuration> 內部使用 <springProfile>,然后在 name 屬性里設置profiles。如下:
<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>
<springProfile name="dev, staging">
    <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>
<springProfile name="!production">
    <!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>
 
<springProperty> 標簽可以使用Spring Environment 中的properties。
<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
        defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
    <remoteHost>${fluentHost}</remoteHost>
    ...
</appender>
關鍵:scope、source、defaultValue。
 
 
 
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

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



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