Spring Boot
Application事件和监听器
除了常见的Spring 框架事件,比如ContextRefreshedEvent,SpringApplication 也会发送其他的application事件。
有些事件实际是在ApplicationContext 创建前触发的,所以你不能在这些事件(处理类)中通过@Bean注册监听器,只能通过SpringApplication.addListeners(...)
或者 SpringApplicationBuilder.listeners(...)
方法注册。 如果想让监听器自动注册,而不关心应用的创建方法,你可以在工程中添加一个META-INF/spring.factories
文件,并使用org.springframework.context.ApplicationListener
作为key 指向那些监听器,如下:
1 | org.springframework.context.ApplicationListener = com.example.project.MyListener |
应用运行时,事件会以下面的次序发送:
- 在运行开始,但除了监听器注册或初始化以外的任务处理之前,会发送一个ApplicationStartedEvent.
- 在Environment将被用于已知的上下文,但在上下文被创建前,会发送一个
ApplicationEnvironmentPreparedEvent
- 在refresh开始前,但在bean定义已被加载后,会发送一个
ApplicationPreparedEvent
。 - 在refresh之后,相关的回调处理完成,会发送一个
ApplicationReadyEvent
表示应用准备好接受请求了。 - 启动过程如果出现异常,会发送一个
ApplicationFailedEvent
。
spring.factories(学习整理一下)
官方start格式:spring-boot-start-xxx
个人start格式:xxx-spring-boot-start
编写自定义的spring-boot-start 需要借助与 spring.factories,具体的 start 编写方式下方有说明。
java:comp (学习整理一下)
@ConfigurationProperties
Relaxed绑定
Spring Boot 将Environment
属性绑定到@ConfigurationProperties
beans 时会使用一些宽松的规格,所以Environment
属性名和bean属性名不需要精确匹配。常见的示例中有用的包括虚线分割(比如:context-type 绑定到 contextPath),将environment属性转为大写字母(比如, PORT 绑定到 port
)
1 | @ConfigurationProperties(prefix="person") |
下面的属性名都能使用:
属性 | 说明 |
---|---|
person.firstName |
标准驼峰规则 |
person.first-name |
虚线表示,推荐用于 .properties 和 .yml文件中 |
person.first_name |
下划线表示,用于 .properties 和 .yml 文件的可选格式 |
PERSON_FIRST_NAME |
大写形式,使用系统环境变量时推荐 |
@ConfigurationProperties VS @Value
@Value
是Spring 容器的一个核心特性,它没有提供跟 type-safe Configuration Properties 相同的特性。下面的表格总结了@ConfigurationProperties
和 @Value
支持的特性:
特性 | @Configuration |
@Value |
---|---|---|
Relaxd绑定 | Yes | NO |
Meta-data支持 | Yes | NO |
SpEL 表达式 | NO | Yes |
如果为自己的组件定义了一些列的keys,那么建议将他们以 @ConfigurationProperties
注解的POJO进行分组。由于 @Value
不支持relaxed绑定,所有如果你使用环境变量属性提供值得话,它就不是很好的选中。最后,尽管 @Value
可以SpEL
表达式,但这些表达式不会出来来自Application
的属性。
自动配置 auto-configuration
从底层讲,自动配置(auto-configurtaion) 是通过标准的@Configuration
类实现的。此外,@Conditional
注解用来约束自动配置生效的条件。通常自动配置类需要使用@conditionOnClass
和 @ConditionOnMissingBean
注解,这是为了确保只有在相关的类被发现及没有声明自定义的 @Configuration
时才应用自动配置,具体查看 spring-boot-autofigure
源码中的 @Configuration
类(META-INF/spring.factories
文件)
Spring Boot 会自动检查你发布的jar是否存在 META-INF/spring.factories
文件,该文件中以EnableAutoCOnfiguration
为空key的属性应该列出你的配置类
1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.mycirp.libx.autoconfigure.LibXAutoConfiguration,\com.mycorp.libx.autoconfiguration.LibXWebAutoConfiguration |
可以使用 @AutoConfigureAfter
或@AutoConfigureBefore
注解为配置类指定特定的顺序。例如,你提供了web-specific 配置,你的类就需要应用在WebMvcAutoConfiguration
后面。
也可以使用 @AutoConfigureOrder
注解为那些相互不知道存在的自动配置类提供排序,该注解语义跟常规的 @Order
注解相同,但专为自动配置提供顺序。
注 自动配置类在只能通过这种方式加载,确保它们定义在一个特殊的package中,特别不能成为组件扫描的目标。
条件注解
@ConditionOnMissingBean
注解是一个常见的示例,开发者可以用它覆盖自动配置类提供的默认行为。
Spring Boot 包含很多@Conditonal
注解,你可以在自己的代码中通过注解@Configuration
类或单独的@Bean
方法来重用它们。
Class 条件
@ConditionalOnClass
和 @ConditionalOnMissingClass
注解可以根据特定类是否出现来决定配置的包含,由于注解元数据是使用 ASM 来解析的,所以你可以使用 value
属性来引用真正的类,即使该类没有出现在运行的应用的classpath下,也可以使用name
属性如果你倾向于使用字符串作为类型。
Bean 条件
@ConditionalOnBean
和 @ConditionalOnMissingBean
注解可以根据特定类是否存在决定bean的包含,你可以使用value属性指定beans(by type) ,也可以使用 name 定义beans (by name), search 属性用于限制搜索beans是需要考虑ApplicationContext层次。
注 需要注意bean自定义添加的顺序,因为这些条件的计算是基于目前处理内容的。出于这个原因,我们推荐在自动配置类中只使用 @ConditionOnBean
和 @ConditionOnMissingBean
注解(即使保证他们在其他用户定义的beans后面加载)
注 @ConditionalOnBean
和 @ConditionalOnMissingBean
不会阻止 @Configuration 类的创建,在类级别使用那些conditions跟使用注解标记每个@Bean方法是等价的。
Property 条件
@ConditionalOnProperty
注解可以根据一个Spring Environment
属性来决定是否包含配置,使用 prefix
和 name
属性指定要检查的配置。默认情况下,任何存在的主要不是 false
的属性都会匹配,你也可以使用havingValue
和 matchIfMissing
属性创建更高级的检测。
matchIfMissing
当配置文件不存在 prefix
.name
值是默认为true还是false,true任务匹配成功havingValue
是一个字符串 与 文件中配置的prefix
.name
进行equal 比较
1 | @ConditionalOnProperty(prefix = "example.service", value = "enabled", matchIfMissing = true),当配置文件中example.service.enabled=true时进行自动配置,如果没有设置此值就默认使用matchIfMissing对应的值 |
Resource条件
@ConditionalOnResource
注解只在特定资源出现时才会包含配置,可以使用常见的Spring约定命名资源,例如file://home/user/test.dat
Web Application条件
@ConditionalOnWebApplication
和 @ConditonalOnNotWebApplication
注解可以根据应用是否为’web应用’来决定是否包含配置,web应用是任何使用Spring WebApplicationContext
,定义一个 session
作用域,或有一个 StandardServeltEnvironment
的应用。
SpEL表达式条件
@ConditionalOnExpression
注解可以根据SpEL表达式结果来决定是否包含配置。