上一节解释了,对事件多路广播器的初始化,initApplicationEventMulticaster
方法创建了广播器SimpleApplicationEventMulticaster
,其父类AbstractApplicationEventMulticaster
的ListenerRetriever
内部类封装了监听器。
这节我们讲讲广播器与监听器的绑定
注册监听器
protected void registerListeners() {
// Register statically specified listeners first.
//遍历所有的监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
//将监听器到广播器中的ListenerRetriever里面的applicationListeners(ApplicationListener)集合
//之后在finishRefresh中发布事件时,用于获取监听器集合(下面讲)
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
//得到所有监听器的Name
//为什么要监听器的Name,因为ListenerRetriever类是对监听器的封装,其中类中有该字段
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
//遍历所有的监听器Name
for (String listenerBeanName : listenerBeanNames) {
//将监听器的名字添到广播器中的ListenerRetriever里面的applicationListenerBeans(String)集合
//之后在finishRefresh中发布事件时,也是用于获取监听器集合(下面讲)
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
//发布早期的事件,earlyApplicationEvents默认为空
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
解释上面添加监听器和Name的原因,因为下面方法中的defaultRetriever
就是封装监听器的ListenerRetriever
类对象,而类定义中用到了这两个字段!
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.retrievalMutex) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
//添加监听器
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
@Override
public void addApplicationListenerBean(String listenerBeanName) {
synchronized (this.retrievalMutex) {
//添加监听器名称
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
this.retrieverCache.clear();
}
}
private class ListenerRetriever {
//监听器集合
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
//监听器Name
public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
//获得监听器集合
public Collection<ApplicationListener<?>> getApplicationListeners() {
//下面省略to do....
}
}
广播器执行所有有监听器的事件
protected void finishRefresh() {
//只看这个方法
// Publish the final event.
//发布事件
publishEvent(new ContextRefreshedEvent(this));
}
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 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
//earlyApplicationEvents默认为空
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
//获取事件广播器,发布事件
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);
}
}
}
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//起一个线程池
Executor executor = getTaskExecutor();
//getApplicationListeners获取监听器集合
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
//执行事件
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
finishRefresh
→publishEvent
→multicastEvent
→getApplicationListeners
→getApplicationListeners
→retrieveApplicationListeners
一直看到这,才明了
synchronized (this.retrievalMutex) {
listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
}
之后从而得到所有监听器,封装为allListeners
监听器链表返回!然后调用线程执行invokeListener
方法一直到doInvokeListener
方法执行监听器事件
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
//执行监听器的事件
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
例子
写一个事件类
public class MyEvent extends ApplicationEvent {
User user;
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public MyEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
写一个事件监听器,必须将其放入IOC容器
@Component
public class MyListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
User user = event.getUser();
System.out.println(user.getName());
}
}
public class test {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
//事件机制测试
User user = new User();
user.setName("lpf");
ac.publishEvent(new MyEvent("",user));
}
}
AbstractApplicationContext
中publishEvent
方法ClassPathXmlApplicationContext
继承了AbstractApplicationContext
,因此ClassPathXmlApplicationContext
可以发布事件!
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
最后打印出lpf