Spring源码:注册监听器和执行事件和registerListeners+finishRefresh源码

上一节解释了,对事件多路广播器的初始化,initApplicationEventMulticaster方法创建了广播器SimpleApplicationEventMulticaster,其父类AbstractApplicationEventMulticasterListenerRetriever内部类封装了监听器。

这节我们讲讲广播器与监听器的绑定

注册监听器

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);
			}
		}
	}

finishRefreshpublishEventmulticastEventgetApplicationListenersgetApplicationListenersretrieveApplicationListeners
一直看到这,才明了

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));
    }
}

AbstractApplicationContextpublishEvent方法ClassPathXmlApplicationContext 继承了AbstractApplicationContext,因此ClassPathXmlApplicationContext可以发布事件!

public interface ApplicationEventPublisher {
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}
	void publishEvent(Object event);
}

最后打印出lpf

猜你喜欢

转载自blog.csdn.net/StrawberryMuMu/article/details/103091611