|
一、SpringApplication banner,就是啟動時(shí)輸出的信息,可以在classpath下添加 banner.txt,或者設(shè)置 banner.location 來指向特定的文件。(默認(rèn)編碼utf-8,或者通過banner.charset指定)
除了txt,你還可以使用 banner.gif (jpg / png),或者設(shè)定 banner.imgage.location。
下面是默認(rèn)的banner(忽略吧,沒意義的東西):
banner變量,只有應(yīng)用相關(guān)的信息,略,見pdf。
還可以使用通過 SpringApplication.setBanner(…) 來設(shè)置。通過實(shí)現(xiàn) org.springframework.boot.Banner 接口,可以實(shí)現(xiàn)自己的 printBanner() 。
通過設(shè)置 spring.main.banner-mode 來決定是否在
System.out (console) 上顯示banner。使用配置的logger (log)或者全不用 (off)。 輸出的banner會被注冊成一個單例的bean,名字springBootBanner。
如果,你想創(chuàng)建一個分層次的ApplicationContext (多個context,有父子關(guān)系),可以使用 SpringApplicationBuilder 。它可以讓你鏈?zhǔn)秸{(diào)用方法,并且設(shè)置父子關(guān)系。如下:
new SpringApplicationBuilder() .bannerMode(Banner.Mode.OFF) .sources(Parent.class) .child(Application.class) .run(args); SpringApplicationBuilder使用起來有一些限制,詳見javadoc。
Application事件和監(jiān)聽器
除了Spring框架的事件(如ContextRefreshedEvent)之外,SpringApplication還提供了一些額外的事件。
但是,有些事件是在ApplicationContext創(chuàng)建之前,所以無法通過@Bean形式注冊監(jiān)聽器??梢酝ㄟ^SpringApplication.addListeners(...) 或者 SpringApplicaitonBuilder.listeners(...) 來注冊。
另外,如果想以與application創(chuàng)建形式無關(guān)的方式來注冊listeners,可以這樣做:創(chuàng)建一個 META-INF/spring.factories 文件。內(nèi)容如下:
org.springframework.context.ApplicationListener=com.example.project.MyListener 多個監(jiān)聽器,應(yīng)該用逗號連接吧???
Application Events,以下面的順序發(fā)送:
沒必要使用這些事件,但是了解一下還是挺有用的。Spring Boot內(nèi)部使用這些事件來處理很多任務(wù)。
Web 環(huán)境
SpringApplication 會試圖創(chuàng)建正確的 ApplicationContext。默認(rèn)的,使用 AnnotationConfigApplicationContext 或者 AnnotationConfigEmbeddedWebApplicationContext ,這取決于是否web應(yīng)用。
可以使用覆蓋 setWebEnvironment(boolean webEnvironment) 默認(rèn)設(shè)置。
也可以使用 setApplicationContextClass(…) 來控制 ApplicationContext 的類型。
注意:當(dāng)在JUnit環(huán)境下使用SpringApplication時(shí),通常需要設(shè)置 setWebEnvironment(false) 。
訪問應(yīng)用的參數(shù)
如何訪問傳遞給SpringApplication.run(...) 的參數(shù)?
你可以注入一個 org.springframework.boot.ApplicationArguments bean。這是一個接口,提供了 String[] 和 option/non-option 參數(shù)形式。
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啟動后執(zhí)行一些特定的代碼,可以讓這些代碼實(shí)現(xiàn)
ApplicationRunner or CommandLineRunner 接口。二者都提供了一個run(),可以在SpringApplication.run(...) 完成之前被調(diào)用。區(qū)別:
CommandLineRunner 只提供對傳遞參數(shù)的默認(rèn)訪問形式 String[],而 ApplicationRunner 則使用了上面提到的 ApplicationArguments 接口。如果,定義了多個
CommandLineRunner or ApplicationRunner beans,那么可以通過實(shí)現(xiàn) org.springframework.core.Ordered 接口或使用 org.springframework.core.annotation.Order 注解來控制加載順序。Application exit
每一個 SpringApplication 都注冊了一個shutdown hook with JVM,以確保 ApplicationContext 順利的關(guān)閉。所有的Spring生命周期中的回調(diào)(如 DisposableBean 接口,或者 @PreDestroy 注解)都可以使用。
另外,如果想在應(yīng)用退出時(shí)返回特定的exit code,那beans可以實(shí)現(xiàn) org.springframework.boot.ExitCodeGenerator 接口。
個人經(jīng)驗(yàn):同樣可以使用@Order控制順序,只不過相反。
個人經(jīng)驗(yàn):使用@Order控制的順序,不能打破大的順序。例如上面(ApplicationRunner or CommandLineRunner)的順序,永遠(yuǎn)在SpringApplication啟動完成之前調(diào)用。
Admin features(略)Externalized Configuration(需要認(rèn)真看看)外來配置?就是說,通過設(shè)定這些配置,可以在不同的工作環(huán)境下運(yùn)行相同的代碼達(dá)到相同的目的。
Spring Boot支持的:properties文件、yaml文件、environment 變量、命令行參數(shù)。
然后,可以通過 @Value 注解注入到bean中,或者通過Spring 的 Environment 訪問,或者通過 @ConfigurationProperties 綁定到結(jié)構(gòu)化對象中。
個人經(jīng)驗(yàn):@Value 的工作是在SpringApplication啟動完成之后進(jìn)行的,在此之前值為null。
注意:不同方式的配置的優(yōu)先級不一樣?;旧?,除了測試情況外,命令行參數(shù)優(yōu)先級最高。尤其要注意指定profile下的優(yōu)先級比默認(rèn)的高。具體如下:
Configuring random valuesRandomValuePropertySource 用于注入隨機(jī)數(shù)值,它可以生成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默認(rèn),SpringApplication會將任何命令行參數(shù)(以--開頭,如--server.port=8900)轉(zhuǎn)成一個property,并添加到Spring Environment中。
再次強(qiáng)調(diào):命令行參數(shù)的優(yōu)先級最高。
如果不想添加到Spring Environment中,你可以禁用它們: SpringApplication.setAddCommandLineProperties(false) 。
關(guān)于application.properties文件
SpringApplication默認(rèn)從以下地址加載,并添加到Spring Environment 中。
/config / classpath/ classpath/config 注意,優(yōu)先級從上往下依次降低。
如果不想使用默認(rèn)的名字,可以自行指定(兩種方式):
java -jar myproject.jar --spring.config.name=myproject java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties 注意,默認(rèn)的加載地址永遠(yuǎn)有效,但可以添加新的,且新的地址的優(yōu)先級更高。
注意,多數(shù)系統(tǒng)的環(huán)境變量不允許使用點(diǎn)分隔的鍵名,可以使用下劃線代替。如: SPRING_CONFIG_NAME 代替 spring.config.name 。
另外,如果在容器中執(zhí)行,還可以使用JNDI properties或者 Servlet Context初始化參數(shù)。
Profile-specific properties
在 application.properties 之外,還會加載 application-{profile}.properties 。由于 Environment 提供了一個默認(rèn)的profile,所以,默認(rèn)還會加載 application-default.properties 。
奇怪,這什么意思:
properties中的占位符
application.properties 中的值是按順序加載到已有的 Environment 中,所以,后面的值可以使用前面的值,使用方法就是占位符。如下:
可以利用該技術(shù)創(chuàng)建短的變量?
YAML是JSON的超集?。裕?/div>
classpath中只要有SnakeYAML 庫,SpringApplication就可以自動支持YAML。
而,Starters默認(rèn)就含有SnakeYAML 庫。
類型安全的Configuration Properties
這里的意思是說,通過Java類來確保類型安全,但值還是要在YAML中提供?。?!
那么,@Value("${property}") 和@ConfigurationProperties 的區(qū)別? 暫略。
注意:通過 @ConfigurationProperties 類進(jìn)行的properties設(shè)置,需要在 @Configuration 類上開啟 @EnableConfigurationProperties 注解才行,而且,需要手動添加 @ConfigurationProperties 類,如下:
@Configuration @EnableConfigurationProperties(ConnectionProperties.class) public class MyConfiguration { }
需要注意的是, @ConfigurationProperties 類對應(yīng)的bean有一個約定好的名字: <prefix>-<fqn> 。fqn是full qualified name。
前面的例子,對應(yīng)的名字是: connection-com.example.ConnectionProperties ,這里假定它在包 com.example 中。
但是,@ConfigurationProperties 類對應(yīng)的bean還有一個默認(rèn)的名字?。?!只是,不建議在environment之外使用而已。
除了上面的紅字部分,由于 @EnableConfigurationProperties 注解 會被自動應(yīng)用到項(xiàng)目中,所以,只要確保 @ConfigurationProperties 類 是一個bean(即@Component),就會被自動添加到 Environment 。如下:
@Component //確保是一個bean即可! @ConfigurationProperties(prefix="connection") public class ConnectionProperties { // ... getters and setters of username and remoteAddress, and so on } 這種形式的配置可以和YAML配置完美的配合。為什么要配合?因?yàn)樯厦嬷皇穷愋桶踩?,沒有值?。?!
# application.yml
connection:
username: admin
remoteAddress: 192.168.1.1
# additional configuration as required
個人經(jīng)驗(yàn):奇怪,為什么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 可以綁定如下內(nèi)容:
Properties conversion,轉(zhuǎn)換,類似SpringMVC的轉(zhuǎn)換
如果要自定義類型轉(zhuǎn)換,三種方式:創(chuàng)建一個 ConversionService bean,或者創(chuàng)建一個 property editors(通過 CustomEditorConfigurer bean),或者創(chuàng)建一個 Converters (@ConfigurationPropertiesBinding)。
注意:這個bean在應(yīng)用早期被調(diào)用,所以,注意限制它的依賴!
@ConfigurationProperties validation
Spring Boot默認(rèn)使用JSR-303去校驗(yàn),所以可以使用JSR-303的注解。如下:
如果有嵌套屬性,需要使用@Valid來觸發(fā)校驗(yàn)。如:
@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 模塊有一個端點(diǎn),對外暴露了所有的 @ConfigurationProperties beans。瀏覽器中訪問 /configprops 即可。也可以使用相應(yīng)的JMX端點(diǎn)???
個人經(jīng)驗(yàn):其實(shí)還有很多地址,詳見啟動信息。如下:
![]() @Value("${property}") 和@ConfigurationProperties 的區(qū)別
@Value 是core container的feature。不支持靈活綁定,不支持Meta-data。但支持spELl。
@ConfigurationProperties 則支持靈活綁定,支持Meta-data。但不支持spELl。
官方指導(dǎo)里推薦使用后者。
Profiles
@Profile 可以用于 @Component 或 @Configuration 。
使用
spring.profiles.activeEnvironment property 來指定運(yùn)行時(shí)的 profile 。如:#application.properties spring.profiles.active=dev,hsqldb #command line argument --spring.profiles.active=dev,hsqldb 有時(shí)候,添加profile 比替換profile 更有用。
spring.profiles.include property 可以做到無條件的添加profile。
SpringApplication也提供了API來添加profile: setAdditionalProfiles() 。
還可以使用 Spring的 ConfigurableEnvironment 接口(實(shí)驗(yàn)了下,太麻煩,不建議使用)。
問題:@Profile在類上和在方法上,是怎么結(jié)合的???怎么出問題了。
Logging
Spring Boot 使用JCL接口,但未指定實(shí)現(xiàn)。默認(rèn)的實(shí)現(xiàn)包括JUL、Log4j2、Logback。均已設(shè)置console輸出。
如果使用Starter模塊,則使用Logback。
Log Level:ERROR, WARN, INFO, DEBUG or TRACE
注意,Logback沒有FATAL,如果設(shè)置了FATAL,會被映射成ERROR。
開啟debug模式:--debug,或者在 application.properties:debug=true。
注意,是debug模式,不是DEBUG Level。
彩色輸出
終端支持ANSI才行,不過現(xiàn)在還有不支持的嗎?
需要設(shè)置 spring.output.ansi.enabled 。
STS中以Spring Boot Application啟動時(shí),應(yīng)該默認(rèn)設(shè)置了。
問題是,為什么我直接以Java Application啟動就不行?-- 因?yàn)闆]有設(shè)置顏色。囧~~
File output
默認(rèn)Log只會ouput到console。如果想輸出到File,應(yīng)該設(shè)置
logging.file 或者logging.path property 。![]() 注意:輸出文件大小到達(dá)10 Mb時(shí),會重新開始?
注意:logging系統(tǒng)是在應(yīng)用的早期初始化的,所以,不能在通過 @PropertySource 加載的文件中配置。
注意:logging properties 與實(shí)際的logging系統(tǒng)無關(guān),所以,Spring Boot不會管理具體的配置文件,如 logback.configurationFile 或 logback.xml 。 會加載,會執(zhí)行,但與Spring Boot無關(guān),是logging系統(tǒng)自己的東西。
Log Levels
所有Spring Boot支持的logging系統(tǒng),都可以在Spring Environment 中設(shè)置(如application.properties),格式:logging.level.*=LEVEL。
其中,LEVEL可以是TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF。
root logger可以使用 logging.level.root 設(shè)置。如下:
logging.level.root=WARN logging.level.org.springframework.web=DEBUG logging.level.org.hibernate=ERROR
自定義log配置
可以使用不同的logging系統(tǒng),只要在classpath中添加相應(yīng)的jars即可。更進(jìn)一步,還可以在classpath提供一個相應(yīng)的配置文件,或者在一個指定的位置(需要使用 logging.config 來指定)。
也可以使用一個特定的logging系統(tǒng),使用 org.springframework.boot.logging.LoggingSystem 來指定,注意,該鍵對應(yīng)的值是具體logging實(shí)現(xiàn)的全路徑,如為none,則默認(rèn)完全禁用Spring Boot的logging配置。
再次提醒:logging系統(tǒng)初始化較早,不能使用 @Configuration 里的 @PropertySources 來控制。
根據(jù)不同的logging實(shí)現(xiàn),加載不同的配置文件。如下:
警告:直接運(yùn)行fat jar時(shí),JUL會有問題,建議避免使用它。
個人問題: Spring Environment 和 System properties 什么關(guān)系?為什么書上說一些properties會從前者傳到后者,以幫助自定義?
注意,如果要使用占位符,應(yīng)該使用Spring Boot的,而非Spring的。
例子就是Logback的分隔符,應(yīng)該用“:”,而非“:-”。
提示:SB包含了Logback的大量擴(kuò)展,用于協(xié)助配置。可以在 logback-spring.xml 中使用它們。
注意:不能在 logback.xml 中使用這些擴(kuò)展,因?yàn)樗患虞d的太早了。
Profile-specific Configuration (logging)
可以在 <configuration> 內(nèi)部使用 <springProfile>,然后在 name 屬性里設(shè)置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> 標(biāo)簽可以使用Spring Environment 中的properties。
|
|
|