文章图片
概念
在一个完整的事件体系中、存在以下的角色
- 事件:描述发生了什么事情、比如说请求处理完成、Spring 容器刷新完毕
- 事件源:事件的产生者、任何一个事件都必须有一个事件源。比如请求处理完成的事件源就是
DispatcherServlet
、Spring 容器刷新完毕的事件源就是ApplicationContext
- 事件广播器:事件和事件监听器的桥梁、负责把事件通知给事件监听器
- 事件监听器:监听事件的发生、可以在监听器中做一些处理
文章图片
我们常见的事件可能就是
ApplicationContextEvent
、它的子类 ContextRefreshedEvent
是我们常见的事件类型、在 Spring 将所有非延迟加载的 bean 实例化之后发布。文章图片
再来看看 Spring 事件的体系结构
文章图片
Spring 监听器
文章图片
【Spring|Spring 事件机制】事件广播器
文章图片
文章图片
ApplicationContext 对事件的支持
文章图片
ApplicationEventPublisher 这个是 Spring 提供给用户使用的一个事件发布器啊、真正实现发布功能还是委托给上面的 ApplicationEventMulticaster 去实现的。
Spring 提供了 ApplicationEventPublisherAware 让用户可以去获取这个发布器进行事件发布。
使用方式
Spring 提供了两种方式
- 实现 ApplicationListener 接口
- 使用注解 @EventListener
public interface SmartInitializingSingleton {/**
* Invoked right at the end of the singleton pre-instantiation phase,
* with a guarantee that all regular singleton beans have been created
* already. {@link ListableBeanFactory#getBeansOfType} calls within
* this method won't trigger accidental side effects during bootstrap.
* NOTE: This callback won't be triggered for singleton beans
* lazily initialized on demand after {@link BeanFactory} bootstrap,
* and not for any other bean scope either. Carefully use it for beans
* with the intended bootstrap semantics only.
*/
void afterSingletonsInstantiated();
}
文章图片
其实实现逻辑非常简单
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
if (factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
ApplicationListener> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
context.addApplicationListener(applicationListener);
break;
}
}
}
找出所有被注解修饰的方法、然后分别创建一个对应的 ApplicationListener、收到事件后反射调用该方法。
public void processEvent(ApplicationEvent event) {
Object[] args = resolveArguments(event);
if (shouldHandle(event, args)) {
Object result = doInvoke(args);
if (result != null) {
handleResult(result);
}
else {
logger.trace("No result object given - no result to handle");
}
}
}
监听器调用的先后顺序
我们可以在 AbstractApplicationEventMulticaster#retrieveApplicationListeners 中看到是支持我们指定监听器的顺序的、Spring 很多涉及顺序的都可以使用
- 实现 Ordered 接口
- 实现 PriorityOrdered 接口
- 使用 @Ordered 接口
默认情况下、Spring 创建的事件广播器是采用同步方式调用通知监听器的、我们可以设置或者替换 Spring 默认的监听器来达到异步调用的目的、当然也可以扩展、根据事件的不同采用同步或者异步的方式、而不是单一的要么所有同步要么所有异步
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
Spring refresh 之前回初始化事件传播器
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
替换原来的事件传播器
@Component("applicationEventMulticaster")
public class TestEventMulticaster extends SimpleApplicationEventMulticaster {
}