初始器 ApplicationContextInitializer
是什么?
ApplicationContext
是 Spring 的核心容器。Spring 为了更灵活的配置 ApplicationContext
,在容器初始化的过程中,允许我们对 ApplicationContext
做进一步的设置和处理,提供了一个 ApplicationContextInitializer
的扩展点。
ApplicationContextInitializer
是一个回调函数,在容器刷新之前会调用该类的 initialize
方法
@FunctionalInterface
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}
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 提供了扩展 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
BeanDefinition
实例之后生效的,用于处理注册实例过程中产生的告警信息,其实就是通过日志打印出告警信息context.initializer.classes
指定的初始化器 (initializers
) 进行初始化工作,如果没有指定则什么都不做。application.properties
里成为了可能。ApplicationContext
增加了个监听器,都是监听 RSocketServerInitializedEvent
事件,为环境 Environment
中添加一个属性源,不同之处在于一个是增加 SocketPort
,一个是增加 ServerPort。监听器 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
继承自 jdk 的 EventObject
,所有的事件都需要继承 ApplicationEvent
,并且通过 source 得到事件源。ContextStartedEvent
:ApplicationContext 启动事件;ContextRefreshedEvent
:ApplicationContext 更新事件;ContextStoppedEvent
:ApplicationContext 停止事件;ContextClosedEvent
:ApplicationContext 关闭事件。ApplicationListener
继承自 jdk 的 EventListener
,该类中只有一个方法 onApplicationEvent
。ApplicationContext
是 Spring 中的核心容器,在事件监听中 ApplicationContext
可以作为事件的发布者,也就是事件源。因为 ApplicationContext
继承自 ApplicationEventPublisher
。在 ApplicationEventPublisher
中定义了事件发布的方法:publishEvent(Object event)
Applicationcontext
发布的 Event
广播给它的监听器列表。首先 Spring Boot 也为 ApplicationContextEvent
提供了几种事件:
ApplicationStartedEvent
:Spring Boot 启动开始时执行的事件ApplicationEnvironmentPreparedEvent
:Spring Boot 对应 Enviroment 已经准备完毕,但此时上下文context还没有创建。ApplicationPreparedEvent
:Spring Boot 上下文 context 创建完成,但此时 Spring 中的 bean 是没有完全加载完成的。ApplicationFailedEvent
: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
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"));
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());
}
}