http://www.cnblogs.com/larryzeal/p/5799633.html
一、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,以下面的顺序发送:
-
ApplicationStartedEvent 应用启动时发送,是除了注册监听器和初始化之外最早的。
-
ApplicationEnvironmentPreparedEvent 创建context之前,已知道context需要使用的Environment时。
-
ApplicationPreparedEvent 发生在context刷新之前,但在bean 定义加载之后。
-
ApplicationReadyEvent 发生在刷新和任何相关回调被处理之后,表明应用已准备好响应请求了。
-
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 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下的优先级比默认的高。具体如下:
-
@TestPropertySource annotations on your tests.
-
Command line arguments.
-
Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)
-
ServletConfig init parameters.
-
ServletContext init parameters.
-
JNDI attributes from java:comp/env.
-
Java System properties (System.getProperties()).
-
OS environment variables.
-
A RandomValuePropertySource that only has properties in random.*.
-
Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
-
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
-
Application properties outside of your packaged jar (application.properties and YAML variants).
-
Application properties packaged inside your jar (application.properties and YAML variants).
-
@PropertySource annotations on your @Configuration classes.
-
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 中,所以,后面的值可以使用前面的值,使用方法就是占位符。如下:
-
app.name=MyApp
-
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有一个约定好的名字:
- 。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.activeEnvironment 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)
可以在 内部使用 ,然后在 name 属性里设置profiles。如下:
<springProfile name="staging"> springProfile> <springProfile name="dev, staging"> springProfile> <springProfile name="!production"> springProfile>
标签可以使用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。