- public class EatEvent extends ApplicationEvent {
- private String status;
- public String getStatus() {
- return status;
- }
- public void setStatus(String status) {
- this.status = status;
- }
- public EatEvent(Object source) {
- super(source);
- }
- }
监听器:
- public class MeListener implements ApplicationListener {
- public void onApplicationEvent(EatEvent event) {
- System.out.println("收到通知,可以去吃饭了");
- }
- }
触发事件:
- public class TestDo implements ApplicationContextAware {
- private ApplicationContext applicationContext;
- public void doTest(){
- applicationContext.publishEvent(new EatEvent(this));
- }
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
- }
以上代码是实际 spring 项目中经常会用到的,利用 spring 的事件机制,可以解耦各个具体监听器,在变化的需求中通过增减监听器来减少具体实现的改动。
spring 核心是管理 bean,而对于这种事件机制,天然有了比较好的实现基础,可以想象这些事件 bean 在初始化时已经被管理器加入到某个注册表里了,然后事件触发时,就要找容器触发。
网上找的完整的相关类图:
源码实现部分:
首先我们在创建一个 Listener 的时候,需要把这个 bean 交给容器管理,由 EventMulticaster 来管理,从 applicationContext.publishEvent(new EatEvent("")) 为入口来看源码。
- public void publishEvent(ApplicationEvent event) {
- publishEvent(event, null);
- }
- protected void publishEvent(Object event, ResolvableType eventType) {
- Assert.notNull(event, "Event must not be null");
- if (logger.isTraceEnabled()) {
- logger.trace("Publishing event in " + getDisplayName() + ": " + event);
- }
- // Decorate event as an ApplicationEvent if necessary
- ApplicationEvent applicationEvent;
- if (event instanceof ApplicationEvent) {
- applicationEvent = (ApplicationEvent) event;
- }
- else {
- applicationEvent = new PayloadApplicationEvent(this, event);
- if (eventType == null) {
- eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
- }
- }
- // Multicast right now if possible - or lazily once the multicaster is initialized
- if (this.earlyApplicationEvents != null) {
- this.earlyApplicationEvents.add(applicationEvent);
- }
- else {
- // 获取ApplicationEventMulticaster
- 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);
- }
- }
- }
getApplicationEventMulticaster 拿预备好的事件广播器,可以使用自己实现的事件广播器,初始化是在 AbstractApplicationContext.refresh 方法触发 initApplicationEventMulticaster():
- protected void initApplicationEventMulticaster() {
- ConfigurableListableBeanFactory beanFactory = getBeanFactory();
- // 取applicationEventMulticaster名的bean,如果没有,就用框架的SimpleApplicationEventMulticaster,是个扩展点
- if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
- this.applicationEventMulticaster =
- beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
- if (logger.isDebugEnabled()) {
- logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
- }
- }
- else {
- this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
- beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
- if (logger.isDebugEnabled()) {
- logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
- APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
- "': using default [" + this.applicationEventMulticaster + "]");
- }
- }
- }
SimpleApplicationEventMulticaster 的 multicastEvent(applicationEvent, eventType); 方法:
- public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
- ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
- for (final ApplicationListener listener : getApplicationListeners(event, type)) {
- Executor executor = getTaskExecutor();
- if (executor != null) {
- executor.execute(new Runnable() {
- @Override
- public void run() {
- invokeListener(listener, event);
- }
- });
- }
- else {
- invokeListener(listener, event);
- }
- }
- }
getApplicationListeners 方法来获取对应的监听者:
- protected Collection> getApplicationListeners(
- ApplicationEvent event, ResolvableType eventType) {
- Object source = event.getSource();
- Class sourceType = (source != null ? source.getClass() : null);
- ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
- // Quick check for existing entry on ConcurrentHashMap...
- ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
- if (retriever != null) {
- return retriever.getApplicationListeners();
- }
- if (this.beanClassLoader == null ||
- (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
- (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
- // Fully synchronized building and caching of a ListenerRetriever
- synchronized (this.retrievalMutex) {
- retriever = this.retrieverCache.get(cacheKey);
- if (retriever != null) {
- return retriever.getApplicationListeners();
- }
- retriever = new ListenerRetriever(true);
- // 获取监听者
- Collection> listeners =
- retrieveApplicationListeners(eventType, sourceType, retriever);
- // 进缓存
- this.retrieverCache.put(cacheKey, retriever);
- return listeners;
- }
- }
- else {
- // No ListenerRetriever caching -> no synchronization necessary
- return retrieveApplicationListeners(eventType, sourceType, null);
- }
- }
retrieveApplicationListeners 需要从容器中过滤出对应的监听者的 bean:
事实上,容器预先将监听者的 bean 全部注册到了 defaultRetriever.applicationListeners,每次出发 publish 时,来遍历过滤出后缓存起来。这个注册的操作也是在 AbstractApplicationContext.refresh 方法中的 registerListeners(); 最下面的 AnnotationAwareOrderComparator.sort 用来排序监听者的执行顺序。继承 Ordered 即可。这里我们可以回顾一下这个 refresh 方法的具体代码。以上已经基本看完了怎么讲监听器的获取,再来看一下执行方法的触发,回到 SimpleApplicationEventMulticaster 的 multicastEvent(applicationEvent, eventType); 这里牵涉到同步执行或异步执行这些监听器的问题,默认 spring 是同步执行的,那么在实际场景中我们会因为监听者执行影响住流程,采用异步的方式,如果没有阅读过源码,采取的方式可能会使用在 publish 的时候进行异步化。 但是这里注意到,如果是 publish 的时候进行异步化它依然是一个线程在执行多个监听者,需要一个个去执行。那么这里就有个扩展的入口了那就是 SimpleApplicationEventMulticaster 支持自定义执行者来进行并发执行监听者事件。
- private Collection> retrieveApplicationListeners(
- ResolvableType eventType, Class sourceType, ListenerRetriever retriever) {
- LinkedList> allListeners = new LinkedList>();
- Set> listeners;
- Set listenerBeans;
- synchronized (this.retrievalMutex) {
- listeners = new LinkedHashSet>(this.defaultRetriever.applicationListeners);
- listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
- }
- // 遍历全部监听者,过滤出匹配的
- for (ApplicationListener listener : listeners) {
- if (supportsEvent(listener, eventType, sourceType)) {
- if (retriever != null) {
- retriever.applicationListeners.add(listener);
- }
- allListeners.add(listener);
- }
- }
- if (!listenerBeans.isEmpty()) {
- BeanFactory beanFactory = getBeanFactory();
- for (String listenerBeanName : listenerBeans) {
- try {
- Class listenerType = beanFactory.getType(listenerBeanName);
- if (listenerType == null || supportsEvent(listenerType, eventType)) {
- // 就是这行代码从容器中获取
- ApplicationListener listener =
- beanFactory.getBean(listenerBeanName, ApplicationListener.class);
- if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
- if (retriever != null) {
- retriever.applicationListenerBeans.add(listenerBeanName);
- }
- allListeners.add(listener);
- }
- }
- }
- catch (NoSuchBeanDefinitionException ex) {
- // Singleton listener instance (without backing bean definition) disappeared -
- // probably in the middle of the destruction phase
- }
- }
- }
- AnnotationAwareOrderComparator.sort(allListeners);
- return allListeners;
- }
- Executor executor = getTaskExecutor();
- if (executor != null) {
- executor.execute(new Runnable() {
- @Override
- public void run() {
- invokeListener(listener, event);
- }
- });
- }
实现的时候可以通过继承 SimpleApplicationEventMulticaster 的方式来完成,例子如下:
- public class AsyncApplicationEventMulticaster extends SimpleApplicationEventMulticaster {
- private TaskExecutor taskExecutor = new TaskExecutor() {
- ExecutorService exeserv = Executors.newCachedThreadPool();
- public void execute(Runnable task) {
- exeserv.execute(task);
- }
- };
- protected TaskExecutor getTaskExecutor() {
- return this.taskExecutor;
- }
- }
invokeListener 来执行 onApplicationEvent 方法:
- protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
- ErrorHandler errorHandler = getErrorHandler();
- if (errorHandler != null) {
- try {
- listener.onApplicationEvent(event);
- }
- catch (Throwable err) {
- errorHandler.handleError(err);
- }
- }
- else {
- listener.onApplicationEvent(event);
- }
- }
到这里,就执行到了 onApplicationEvent 方法。
另外,回到最前面的例子中,注意 EatEvent 中那个 source 属性,代表来源的意思,再调用 publish 方法时将 this 传入,那么在筛选监听者的时候,就可以判断是哪个来源的 bean 发起的通知,再进行一次筛选是否执行的逻辑,如此就是监听者可以过滤事件源了。
来源: http://www.cnblogs.com/killbug/p/6418892.html