概述:
在spring 中,一个事件被发布后,当被对应的监听器监听到时,会执行对应的方法。其实该机制就是Observer Pattern (观察者模式) 设计的实现,下面我们通过一个简单的例子进行分析
1. 创建事件
继承 ApplicationEvent ,ApplicationEvent 可以说是 顶级事件
public class OneEvent extends ApplicationEvent {
public OneEvent(Object source) {
super(source);
}
}
2. 进行事件发布 Event publish
note: now we publish given event to all listeners which interest this event
发布事件给对该事件感兴趣的所有listener
public class Controller {
@Resource
private ApplicationEventPublisher eventPublisher;
@PostMapping("/testPub")
public void testPub() {
User user = new User();
OneEvent OneEvent = new OneEvent(user);
// publish given event to all listeners which interest this event
eventPublisher.publishEvent(OneEvent);
}
}
3. 进行事件监听
这里我使用 @EventListener (注解形式)进行事件的监听,他只监听 OneEvent 哦 ~
@Slf4j
@Component
public class TestListener {
@EventListener
public void oneListener(OneEvent oneEvent) {
// process the logic ...
}
}
4. 源码分析 deep the code
先从发布事件开始
// AbstractApplicationContext.java
/**
* Publish the given event to all listeners.
* @param event the event to publish (may be an {@link ApplicationEvent}
* or a payload object to be turned into a {@link PayloadApplicationEvent})
* @param eventType the resolved event type, if known
* @since 4.2
*/
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
// if the ApplicationEvent
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 先看这个,使用mutilcaster广播器 进行 广播
// 1.1 use the mutilcaster to multicast the event ⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎ ⬇︎⬇︎⬇︎
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
//SimpleApplicationEventMulticaster.java
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// get the executor which will execute the task asynchronously
Executor executor = getTaskExecutor();
// 1.2 ⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎
// 获取到对该事件感兴趣的监听器listener,再进行遍历执行
// iterates through all the listeners that are interested in the given event and type. ⬅︎⬅︎⬅︎⬅︎⬅︎
// the getApplicationListeners method is to find the listeners which are interested in the event
// the invoke logic is in the invokeListener. ⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
// async
executor.execute(() -> invokeListener(listener, event));
}
else {
// sync
invokeListener(listener, event); //1.3 ⬇︎⬇︎⬇︎⬇︎⬇︎
}
}
}
//SimpleApplicationEventMulticaster.java
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// invoke the listener method
// 比较核心的是这个
listener.onApplicationEvent(event);
}...
通过 @EventListener 注解方式 和 实现 ApplicationListener 接口 到这一步所处理的方式不一样,不过 目的一样—— 执行 监听器 lisener 中的方法
//ApplicationListenerMethodAdapter.java
/**
* Process the specified {@link ApplicationEvent}, checking if the condition
* matches and handling a non-null result, if any.
*/
public void processEvent(ApplicationEvent event) {
Object[] args = resolveArguments(event);
if (shouldHandle(event, args)) {
// 1.4 invoke the listener method ⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎ ⬇︎⬇︎⬇︎
Object result = doInvoke(args);
if (result != null) {
handleResult(result);
}
else {
logger.trace("No result object given - no result to handle");
}
}
}
//ApplicationListenerMethodAdapter.java
/**
* Invoke the event listener method with the given argument values.
*/
@Nullable
protected Object doInvoke(Object... args) {
// get the listener bean
Object bean = getTargetBean();
// Detect package-protected NullBean instance through equals(null) check
if (bean.equals(null)) {
return null;
}
ReflectionUtils.makeAccessible(this.method);
try {
// 1.5 invoke the method in listener , consume the message ⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎⬅︎
return this.method.invoke(bean, args);
}
catch (IllegalArgumentException ex) {
assertTargetBean(this.method, bean, args);
throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
}
catch (InvocationTargetException ex) {
// Throw underlying exception
Throwable targetException = ex.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
}
else {
String msg = getInvocationErrorMessage(bean, "Failed to invoke event listener method", args);
throw new UndeclaredThrowableException(targetException, msg);
}
}
}