Spring Boot每次发布时都会提供一个它所支持的精选依赖列表。实际上,在构建配置里你不需要提供任何依赖的版本,因为Spring Boot已经替你管理好了。当更新Spring Boot时,那些依赖也会一起更新。
application.properties
和
application.yml进行了资源过滤
${...}
),所以Maven filtering需改用
@..@
占位符(你可以使用Maven属性
resource.delimiter
来覆盖它)
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.4.1.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies></dependencyManagement>
spring-boot-starter-parent
,通过设置
scope=import
的依赖,你仍能获取到依赖管理的,当然这样配置你就不能像上边一样覆盖默认的版本了。当然这也有别的办法,这里就不说了。
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
Starters是一个依赖描述符的集合,你可以将它包含进项目中,这样添加依赖就非常方便。你可以获取所有Spring及相关技术的一站式服务,而不需要翻阅示例代码,拷贝粘贴大量的依赖描述符。例如,如果你想使用Spring和JPA进行数据库访问,只需要在项目中包含spring-boot-starter-data-jpa
依赖,然后你就可以开始了。
该starters包含很多搭建,快速运行项目所需的依赖,并提供一致的,可管理传递性的依赖集。
spring-boot-starter-*
,在这里
*
是一种特殊的应用程序类型。该命名结构旨在帮你找到需要的starter。很多集成于IDEs中的Maven插件允许你通过名称name搜索依赖。例如,使用相应的Eclipse或STS插件,你可以简单地在POM编辑器中点击
ctrl-space
,然后输入"spring-boot-starter"就可以获取一个完整列表。正如Creating your own starter章节中讨论的,第三方starters不应该以
spring-boot
开头,因为它跟Spring Boot官方artifacts冲突。一个acme的第三方starter通常命名为
acme-spring-boot-starter
。
@EnableAutoConfiguration
注解的exclude属性禁用它们
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;
@Configuration@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
如果使用Spring Boot Maven或Gradle插件创建一个可执行jar,你可以使用java -jar
运行应用。例如:
$ java -jar target/myproject-0.0.1-SNAPSHOT.jar
Spring Boot支持以远程调试模式运行一个打包的应用,下面的命令可以为应用关联一个调试器:
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
Spring Boot Maven插件包含一个run
目标,可用来快速编译和运行应用程序,并且跟在IDE运行一样支持热加载。
$ mvn spring-boot:run
你可以使用一些有用的操作系统环境变量:
$ export MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128M
spring-boot-devtools
模块可以included到任何模块中,以提供development-time特性,你只需简单的将该模块的依赖添加到构建中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
java -jar
或特殊的类加载器启动,都会被认为是一个产品级的应用(production application),从而禁用开发者工具。
main()
方法启动Spring应用。多数情况下,你只需要将该任务委托给
SpringApplication.run
静态方法
如果应用启动失败,注册的FailureAnalyzers
就有机会提供一个特定的错误信息,及具体的解决该问题的动作。例如,如果在8080
端口启动一个web应用,而该端口已被占用,那你应该可以看到类似如下的内容:
APPLICATION FAILED TO START
***************************
Description:
Embedded servlet container failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
注 Spring Boot提供很多的FailureAnalyzer
实现,你自己实现也很容易。
如果没有可用于处理该异常的失败分析器(failure analyzers),你需要展示完整的auto-configuration报告以便更好的查看出问题的地方,因此你需要启用org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
的debug属性,或开启DEBUG日志级别。
例如,使用java -jar
运行应用时,你可以通过如下命令启用debug
属性:
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
banner.txt
或设置
banner.location
来指定相应的文件可以改变启动过程中打印的banner。如果这个文件有特殊的编码,你可以使用
banner.encoding
设置它(默认为UTF-8)。除了文本文件,你也可以添加一个
banner.gif
,
banner.jpg
或
banner.png
图片,或设置
banner.image.location
属性。图片会转换为字符画(ASCII art)形式,并在所有文本banner上方显示。
注 如果想以编程的方式产生一个banner,可以使用SpringBootApplication.setBanner(…)
方法,并实现org.springframework.boot.Banner
接口的printBanner()
方法。
你也可以使用spring.main.banner-mode
属性决定将banner打印到何处,System.out
(console
),配置的logger(log
)或都不输出(off
)。
springBootBanner
的单例bean。
SpringApplication
不符合你的口味,你可以创建一个本地实例并对它进行自定义。例如,想要关闭banner你可以这样写:
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
注:传递给SpringApplication
的构造器参数将作为spring beans的配置源,多数情况下,它们是一些@Configuration
类的引用,但也可能是XML配置或要扫描包的引用。
application.properties
文件来配置
SpringApplication
除了常见的Spring框架事件,比如ContextRefreshedEvent,SpringApplication
也会发送其他的application事件。
注 有些事件实际上是在ApplicationContext
创建前触发的,所以你不能在那些事件(处理类)中通过@Bean
注册监听器,只能通过SpringApplication.addListeners(…)
或SpringApplicationBuilder.listeners(…)
方法注册。如果想让监听器自动注册,而不关心应用的创建方式,你可以在工程中添加一个META-INF/spring.factories
文件,并使用org.springframework.context.ApplicationListener
作为key指向那些监听器,如下:
org.springframework.context.ApplicationListener=com.example.project.MyListener
应用运行时,事件会以下面的次序发送:
- 在运行开始,但除了监听器注册和初始化以外的任何处理之前,会发送一个
ApplicationStartedEvent
。 - 在Environment将被用于已知的上下文,但在上下文被创建前,会发送一个
ApplicationEnvironmentPreparedEvent
。 - 在refresh开始前,但在bean定义已被加载后,会发送一个
ApplicationPreparedEvent
。 - 在refresh之后,相关的回调处理完,会发送一个
ApplicationReadyEvent
,表示应用准备好接收请求了。 - 启动过程中如果出现异常,会发送一个
ApplicationFailedEvent
。
SpringApplication
将尝试为你创建正确类型的ApplicationContext
,默认情况下,根据你开发的是否为web应用决定使用AnnotationConfigApplicationContext
或AnnotationConfigEmbeddedWebApplicationContext
。
用于确定是否为web环境的算法相当简单(判断是否存在某些类),你可以使用setWebEnvironment(boolean webEnvironment)
覆盖默认行为。
通过调用setApplicationContextClass(…)
,你可以完全控制ApplicationContext
的类型。
SpringApplication
,调用
setWebEnvironment(false)
是很有意义的
SpringApplication.run(…)
的应用参数,你可以注入一个
org.springframework.boot.ApplicationArguments
类型的bean。
ApplicationArguments
接口即提供对原始
String[]
参数的访问,也提供对解析成
option
和
non-option
参数的访问:
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*
@Componentpublic 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"]
}
}
Environment
属性的
CommandLinePropertySource
,这就允许你使用
@Value
注解注入单个的应用参数。 所以啊,用注入的更方便
如果需要在SpringApplication
启动后执行一些特殊的代码,你可以实现ApplicationRunner
或CommandLineRunner
接口,这两个接口工作方式相同,都只提供单一的run
方法,该方法仅在SpringApplication.run(…)
完成之前调用。
CommandLineRunner
接口能够访问string数组类型的应用参数,而
ApplicationRunner
使用的是上面描述过的
ApplicationArguments
接口:
import org.springframework.stereotype.*
@Componentpublic class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
CommandLineRunner
或
ApplicationRunner
beans需要以特定的顺序调用,你可以实现
org.springframework.core.Ordered
接口或使用
org.springframework.core.annotation.Order
注解。
Application退出
为确保ApplicationContext
在退出时被平静的(gracefully)关闭,每个SpringApplication
都会注册一个JVM的shutdown钩子,所有标准的Spring生命周期回调(比如DisposableBean
接口或@PreDestroy
注解)都能使用。
org.springframework.boot.ExitCodeGenerator
接口。
Spring Boot允许将配置外部化(externalize),这样你就能够在不同的环境下使用相同的代码。你可以使用properties文件,YAML文件,环境变量和命令行参数来外部化配置。使用@Value注解,可以直接将属性值注入到beans中,然后通过Spring的Environment
抽象或通过@ConfigurationProperties
绑定到结构化对象来访问。
Spring Boot设计了一个非常特别的PropertySource
顺序,以允许对属性值进行合理的覆盖,属性会以如下的顺序进行设值:
- home目录下的devtools全局设置属性(
~/.spring-boot-devtools.properties
,如果devtools激活)。 - 测试用例上的@TestPropertySource注解。
- 测试用例上的@SpringBootTest#properties注解。
- 命令行参数
- 来自
SPRING_APPLICATION_JSON
的属性(环境变量或系统属性中内嵌的内联JSON)。 ServletConfig
初始化参数。ServletContext
初始化参数。- 来自于
java:comp/env
的JNDI属性。 - Java系统属性(System.getProperties())。
- 操作系统环境变量。
- RandomValuePropertySource,只包含
random.*
中的属性。 - 没有打进jar包的Profile-specific应用属性(
application-{profile}.properties
和YAML变量)。 - 打进jar包中的Profile-specific应用属性(
application-{profile}.properties
和YAML变量)。 - 没有打进jar包的应用配置(
application.properties
和YAML变量)。 - 打进jar包中的应用配置(
application.properties
和YAML变量)。 @Configuration
类上的@PropertySource
注解。- 默认属性(使用
SpringApplication.setDefaultProperties
指定)。
@Component
:
import org.springframework.beans.factory.annotation.*
@Componentpublic class MyBean {
@Value("${name}")
private String name;
// ...
}
你可以将一个application.properties
放到应用的classpath下,为name
提供一个合适的默认属性值。当在新的环境中运行时,可以在jar包外提供一个application.properties
覆盖name
属性。对于一次性的测试,你可以使用特定的命令行开关启动应用(比如,java -jar app.jar --name="Spring"
)。
注 SPRING_APPLICATION_JSON
属性可以通过命令行的环境变量设置,例如,在一个UNIX shell中可以这样:
$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar
本示例中,如果是Spring Environment
,你可以以foo.bar=spam
结尾;如果在一个系统变量中,可以提供作为spring.application.json
的JSON字符串:
$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar
或命令行参数:
$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'
java:comp/env/spring.application.json
。
在注入随机值(比如,密钥或测试用例)时RandomValuePropertySource
很有用,它能产生整数,longs或字符串,比如:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
random.int*
语法是
OPEN value (,max) CLOSE
,此处
OPEN,CLOSE
可以是任何字符,并且
value,max
是整数。如果提供
max
,那么
value
是最小值,
max
是最大值(不包含在内)。
默认情况下,SpringApplication
会将所有命令行配置参数(以'--'开头,比如--server.port=9000
)转化成一个property
,并将其添加到Spring Environment
中。正如以上 节提过的,命令行属性总是优先于其他属性源。
Environment
,你可以使用
SpringApplication.setAddCommandLineProperties(false)
来禁用它们。
SpringApplication
将从以下位置加载application.properties
文件,并把它们添加到Spring Environment
中:
- 当前目录下的
/config
子目录。 - 当前目录。
- classpath下的
/config
包。 - classpath根路径(root)。
该列表是按优先级排序的(列表中位置高的路径下定义的属性将覆盖位置低的)。
注 你可以使用YAML('.yml')文件替代'.properties'。
如果不喜欢将application.properties
作为配置文件名,你可以通过指定spring.config.name
环境属性来切换其他的名称,也可以使用spring.config.location
环境属性引用一个明确的路径(目录位置或文件路径列表以逗号分割)。
$ 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.location
决定加载哪个文件,所以它们必须定义为environment属性(通常为OS env,系统属性或命令行参数)。
如果spring.config.location
包含目录(相对于文件),那它们应该以/
结尾(在被加载前,spring.config.name
关联的名称将被追加到后面,包括profile-specific的文件名)。spring.config.location
下定义的文件使用方法跟往常一样,没有profile-specific变量支持的属性,将被profile-specific的属性覆盖。
不管spring.config.location
配置什么值,默认总会按照classpath:,classpath:/config,file:,file:config/
的顺序进行搜索,优先级由低到高,也就是file:config/
获胜。如果你指定自己的位置,它们会优先于所有的默认位置(locations),并使用相同的由低到高的优先级顺序。那样,你就可以在application.properties
为应用设置默认值,然后在运行的时候使用不同的文件覆盖它,同时保留默认配置。
注 如果使用环境变量而不是系统属性,需要注意多数操作系统的key名称不允许以句号分割(period-separated),但你可以使用下划线(underscores)代替(比如,使用SPRING_CONFIG_NAME
代替spring.config.name
)。