时效提示:本文写于 2020 年,基于当时的 Spring Boot 2.x,部分 API、配置和工具版本可能已经变化,参考时请以官方最新文档为准。
背景 && 可能你想干的事
- Spring 程序生命周期
- BeanDefinition 扩展点
- Bean的生命周期
- BeanFactory生命周期
- FactoryBean使用
- Spring 事件 (refresh)
- application.yml => Environment
- 各种 aware
- Condition
1. Spring 程序生命周期
ApplicationRunner&&CommandLineRunner
调用时机=>
org.springframework.boot.SpringApplication#callRunners
use by spring bean
SpringApplicationRunListener
use by META-INF/spring.factories
org.springframework.boot.SpringApplicationRunListener=
com.hafiz.springbootdemo.DemoSpringApplicationRunListener补充:Spring Boot 2.7 起,自动配置类改为在
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中声明,3.0 起spring.factories不再支持注册自动配置;SpringApplicationRunListener、ApplicationContextInitializer等其他扩展仍然通过spring.factories注册。
ApplicationListenerApplicationContextInitializer
这货也是Spring框架原有的东西,这个类的主要作用就是在ConfigurableApplicationContext类型(或者子类型)的ApplicationContext做refresh之前,允许我们对ConfiurableApplicationContext的实例做进一步的设置和处理。
2. BeanDefinition 扩展点
BeanDefinition——spring bean的建模对象
Bean Definition Link
BeanDefinitionRegistryPostProcessor
3. Bean生命周期
BeanPostProcess
InstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor
ApplicationContextAwareProcessor
BeanFactoryAware
InitializingBean
init
DisposableBean
4. BeanFactory
BeanFactoryPostProcessor
5. FactoryBean
FactoryBean 是“生产 Bean 的 Bean”:容器里注册的是这个工厂,getBean 拿到的却是 getObject() 返回的对象。适合创建过程复杂、需要封装的对象,比如给接口生成代理、构建第三方客户端。注意和 BeanFactory(容器本身)区分。
@Component("tool")
public class ToolFactoryBean implements FactoryBean<Tool> {
@Override
public Tool getObject() {
// 复杂的创建逻辑写在这里,例如读取配置、生成代理对象
return new Tool("created by factory");
}
@Override
public Class<?> getObjectType() {
return Tool.class;
}
@Override
public boolean isSingleton() {
return true; // Spring 5 起为默认方法,默认就是 true
}
}
// context.getBean("tool") -> Tool 对象(getObject 的返回值)
// context.getBean("&tool") -> ToolFactoryBean 本身(名字前加 &)典型应用:MyBatis 的 SqlSessionFactoryBean、MapperFactoryBean(为 Mapper 接口生成代理),Spring Cloud OpenFeign 的 FeignClientFactoryBean(为 @FeignClient 接口生成客户端)。
参考:Spring 官方文档:Container Extension Points
6. Spring Event
ContextRefreshedEvent
ContextStartedEvent
ContextStoppedEvent
ContextClosedEvent
RequestHandledEvent
以上是 Spring 容器自带的事件(RequestHandledEvent 只在 Web 应用中出现)。Spring Boot 启动过程还会依次发布:ApplicationStartingEvent → ApplicationEnvironmentPreparedEvent → ApplicationContextInitializedEvent → ApplicationPreparedEvent → ApplicationStartedEvent → ApplicationReadyEvent,失败时发布 ApplicationFailedEvent。
注意:容器刷新之前的事件(Starting、EnvironmentPrepared 等)发生时,用 @Component 注册的监听器还没创建,收不到;要通过 spring.factories 或 SpringApplication#addListeners 注册。
业务里更常用的是自定义事件,用来解耦:
// 1. 定义事件:Spring 4.2 起可以是任意对象,不必继承 ApplicationEvent
public class OrderCreatedEvent {
private final Long orderId;
public OrderCreatedEvent(Long orderId) { this.orderId = orderId; }
public Long getOrderId() { return orderId; }
}
// 2. 发布事件
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
@Transactional
public void create(Order order) {
// ... 保存订单
publisher.publishEvent(new OrderCreatedEvent(order.getId()));
}
}
// 3. 监听事件
@Component
public class OrderEventListener {
// 默认同步执行:和发布方在同一个线程、同一个事务里
@EventListener
public void onCreated(OrderCreatedEvent event) {
// ...
}
// 事务提交成功后才执行,适合发消息、通知等不能回滚的操作
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void afterCommit(OrderCreatedEvent event) {
// ...
}
}@EventListener默认同步,监听器抛异常会影响发布方;需要异步时加@Async(并开启@EnableAsync)。@TransactionalEventListener只在有事务时触发;没有事务时默认不执行,可以设置fallbackExecution = true。
参考:Spring 官方文档:Standard and Custom Events、Spring Boot 官方文档:Application Events and Listeners
7. Environment相关
Environment 是什么? spring 的环境,其包含了相关配置信息,bean的属性注入来源。@Value等的来源。
相关接口 EnvironmentPostProcessor detail -> org.springframework.boot.env.EnvironmentPostProcessor
应用场景1. -> 让@EnableConfigurationProperties的值注入到@Value中
应用场景2. -> 我们引入第三方的jar(巨龙单点登录)使用的是properties配置时,我们可以集成到application.yml中。
应用场景3. -> 不单纯使用application.yml 去管理Environment 可以外部化配置拆分
应用场景4. -> hook 点, 调整Environment 源数据加载顺序。调整相关的优先级等。
8. 各种Aware
各种Aware注入 如常见的注入ApplicationContextAware 用于获取 ApplicationContext。
BeanNameAware
BeanFactoryAware
SmartInitializingSingleton
9. Condition
spring.context => 核心注解@Conditional
常见复合注解 @ConditionalOnClass、 @ConditionalOnProperty 、ConditionalOnMissingBean。 扩展Conditional => SpringBootCondition
一般最常见的是ConditionalOnMissingBean 我们就可以自定义bean,让框架使用我们的bean
如 spring.session.store-type=jdbc => 可以使用内存存储session
Use In Project
- 一般情况注册Bean
- 特殊情况 META-INF/spring.factories
写在最后
以上仅仅是自己工作中总结到的一些点,Spring Boot (Spring Core) 本身扩展点就很多,如果你集成其他框架,那就更多了,所以有时间还是可以多看看源码的。
More and More
