目录
ApplicationContextInitializer
初始器 ApplicationContextInitializer
是什么?
ApplicationContext
是 Spring 的核心容器。Spring 为了更灵活的配置 ApplicationContext
,在容器初始化的过程中,允许我们对 ApplicationContext
做进一步的设置和处理,提供了一个 ApplicationContextInitializer
的扩展点。
ApplicationContextInitializer
是一个回调函数,在容器刷新之前会调用该类的 initialize
方法
@FunctionalInterface
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}
自定义 ApplicationContextInitializer 的方式
- 编码实现
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("MyApplicationContextInitializer initialize");
}
}
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MySpringBootApplication.class);
application.addInitializers(new MyApplicationContextInitializer());
application.run(args);
}
}
- 在
spring-boot-starter
中实现:创建spring.factories
文件:
org.springframework.context.ApplicationContextInitializer=\
com.test.demo.MyApplicationContextInitializer
- 使用
application.properties
配置:
context.initializer.classes=com.test.demo.MyApplicationContextInitializer
Spring Boot 中的 ApplicationContextInitializer
Spring 提供了扩展 ApplicationContextInitializer
的方法,Spring Boot 将其充分地利用了。
Spring Boot 中的 ApplicationContextInitializer
:
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
- ConfigurationWarningsApplicationContextInitializer
用于报告 Spring 容器的一些常见的错误配置,该初始化器为 context 增加了一个 Bean 的后置处理器。这个处理器是在注册BeanDefinition
实例之后生效的,用于处理注册实例过程中产生的告警信息,其实就是通过日志打印出告警信息 - ContextIdApplicationContextInitialize
设置 Spring 应用上下文的ID - DelegatingApplicationContextInitializer
使用环境属性context.initializer.classes
指定的初始化器 (initializers
) 进行初始化工作,如果没有指定则什么都不做。
通过它使得我们可以把自定义实现类配置在application.properties
里成为了可能。 - RSocketPortInfoApplicationContextInitializer、ServerPortInfoApplicationContextInitializer
用于配置环境变量,都是给ApplicationContext
增加了个监听器,都是监听RSocketServerInitializedEvent
事件,为环境Environment
中添加一个属性源,不同之处在于一个是增加SocketPort
,一个是增加 ServerPort。
ApplicationListener
监听器 ApplicationListener
是什么?
org.springframework.context.ApplicationListener
是 Spring 提供的一个接口,是 Spring 事件机制的一部分,需要与 ApplicationEvent
配合完成。
通过 ApplicationContext.publishEvent
发布事件,对应的 listener
会被触发,是典型的观察者模式。
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
Spring 中观察者模式需要的组件:
- ApplicationEvent 事件
ApplicationEvent
继承自 jdk 的EventObject
,所有的事件都需要继承ApplicationEvent
,并且通过 source 得到事件源。
Spring 为我们提供了很多内置的容器事件:ContextStartedEvent
:ApplicationContext 启动事件;ContextRefreshedEvent
:ApplicationContext 更新事件;ContextStoppedEvent
:ApplicationContext 停止事件;ContextClosedEvent
:ApplicationContext 关闭事件。
- ApplicationListener 事件监听者,也就是观察者
ApplicationListener
继承自 jdk 的EventListener
,该类中只有一个方法onApplicationEvent
。
它是 Spring 生命周期各个阶段的监听器,当监听的事件发生后该方法会被执行。 - ApplicationContext 事件源
ApplicationContext
是 Spring 中的核心容器,在事件监听中ApplicationContext
可以作为事件的发布者,也就是事件源。因为ApplicationContext
继承自ApplicationEventPublisher
。在ApplicationEventPublisher
中定义了事件发布的方法:publishEvent(Object event)
- ApplicationEventMulticaster 事件管理
用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把Applicationcontext
发布的Event
广播给它的监听器列表。
Spring Boot 中的 ApplicationListener
首先 Spring Boot 也为 ApplicationContextEvent
提供了几种事件:
ApplicationStartedEvent
:Spring Boot 启动开始时执行的事件ApplicationEnvironmentPreparedEvent
:Spring Boot 对应 Enviroment 已经准备完毕,但此时上下文context还没有创建。ApplicationPreparedEvent
:Spring Boot 上下文 context 创建完成,但此时 Spring 中的 bean 是没有完全加载完成的。ApplicationFailedEvent
:Spring Boot 启动异常时执行事件
Spring Boot 中的ApplicationListener
,这些监听器都是针对上述事件作出处理
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
自定义 ApplicationListener
- 自定义事件
public class MyApplicationEvent extends ApplicationEvent {
public MyApplicationEvent(Object source) {
super(source);
}
}
- 自定义监听器
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
@Override
public void onApplicationEvent(MyApplicationEvent event) {
System.out.println("MyApplicationListener onApplicationEvent , MyApplicationEvent:" + event.getSource());
}
}
- 注册监听器、发布事件
@SpringBootApplication()
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
// 注册监听器
application.addListeners(new MyApplicationListener());
ConfigurableApplicationContext context = application.run(args);
//发布事件
context.publishEvent(new MyApplicationEvent("myApplicationEvent"));
}
}
发布事件 的方式:
- 直接使用
ApplicationContext
发布事件
context.publishEvent(new MyApplicationEvent("myApplicationEvent"));
- 定义事件发布器:向 bean 中注入一个
ApplicationEventPublisher
来发布事件
@Service
public class MyApplicationEventPublisher {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void publishEvent() {
eventPublisher.publishEvent(new MyApplicationEvent("myApplicationEvent"));
}
}
监听事件 的方式
- 直接使用
ApplicationContext
注册监听器
application.addListeners(new MyApplicationListener());
- 使用
@EventListener
监听事件,不必再直接向ApplicationContext
中注册,并且可以在一个 service 中监听多个事件
@Service
public class MyApplicationEventListener {
@EventListener
public void listenMyApplicationEvent(MyApplicationEvent myApplicationEvent) {
System.out.println("MyApplicationListener onApplicationEvent , MyApplicationEvent:" + myApplicationEvent.getSource());
}
}