美文网首页Spring
Spring事件监听详解

Spring事件监听详解

作者: 晴天哥_王志 | 来源:发表于2021-08-07 21:01 被阅读0次

    开篇

    • spring事件分为事件发布者(EventPublisher)、事件监听者(EventListener),还包括一个事件广播者(这个是spring实现相关,这一节不讨论)。
    • 使用spring事件机制,需要自定义事件发布者和监听者。

    使用案例

    // 定义事件
    public class ContentEvent extends ApplicationEvent {  
        public ContentEvent(final String content) {  
            super(content);  
        }  
    }  
    
    // 定义事件监听器
    @Component  
    public class UserOneListener implements ApplicationListener<ApplicationEvent> {  
        @Override  
        public void onApplicationEvent(final ApplicationEvent event) {  
            if(event instanceof ContentEvent) {  
                System.out.println("[UserOneListener]msg:" + event.getSource());  
            }  
        }  
    }
    
    // 测试消息发布
    @RunWith(SpringJUnit4ClassRunner.class)  
    @ContextConfiguration(locations={"classpath:spring-config-hello.xml"})  
    public class HelloIT {  
      
        @Autowired  
        private ApplicationContext applicationContext;  
        @Test  
        public void testPublishEvent() {  
            applicationContext.publishEvent(new ContentEvent("news is  update"));  
        }  
    }  
    
    • 定义事件对象ContentEvent。
    • 定义事件监听器UserOneListener。
    • 通过applicationContext.publishEvent模拟事件发布。

    源码分析

    public abstract class AbstractApplicationContext extends DefaultResourceLoader
            implements ConfigurableApplicationContext, DisposableBean {
            // 事件广播器
        private ApplicationEventMulticaster applicationEventMulticaster;
            // 事件监听者
        private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();
        private Set<ApplicationEvent> earlyApplicationEvents;
    
        @Override
        public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();
    
                // Tell the subclass to refresh the internal bean factory.
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);
    
                try {
                    // Allows post-processing of the bean factory in context subclasses.
                    postProcessBeanFactory(beanFactory);
    
                    // Invoke factory processors registered as beans in the context.
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // Register bean processors that intercept bean creation.
                    registerBeanPostProcessors(beanFactory);
    
                    // Initialize message source for this context.
                    initMessageSource();
    
                    // 初始化Spring的事件广播器
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
                    onRefresh();
    
                    // 注册Spring事件监听器
                    registerListeners();
    
                    // Instantiate all remaining (non-lazy-init) singletons.
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Last step: publish corresponding event.
                    finishRefresh();
                }
                catch (BeansException ex) {
    
                }
                finally {
    
                }
            }
        }
    
    
        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);
            }
            else {
                this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
                beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            }
        }
    
            // 将所有listener注册到applicationEventMulticaster当中
        protected void registerListeners() {
    
            for (ApplicationListener<?> listener : getApplicationListeners()) {
                getApplicationEventMulticaster().addApplicationListener(listener);
            }
    
            String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
            for (String listenerBeanName : listenerBeanNames) {
                getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
            }
    
            Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
            this.earlyApplicationEvents = null;
            if (earlyEventsToProcess != null) {
                for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                    getApplicationEventMulticaster().multicastEvent(earlyEvent);
                }
            }
        }
    
            // 获取所有的listener
        public Collection<ApplicationListener<?>> getApplicationListeners() {
            return this.applicationListeners;
        }
    
        @Override
        public void addApplicationListener(ApplicationListener<?> listener) {
            if (this.applicationEventMulticaster != null) {
                this.applicationEventMulticaster.addApplicationListener(listener);
            }
            else {
                this.applicationListeners.add(listener);
            }
        }
    }
    
    • AbstractApplicationContext作为ApplicationContext的基类,提供广播对象的创建、listener的添加、listener的注册。
    • addApplicationListener负责把通用的listener添加到applicationEventMulticaster当中。
    • initApplicationEventMulticaster负责创建SimpleApplicationEventMulticaster广播对象。
    • registerListeners把添加的listener绑定到SimpleApplicationEventMulticaster当中。
    • 整个核心是把listener绑定到广播对象SimpleApplicationEventMulticaster当中。
    public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
    
        private Executor taskExecutor;
        private ErrorHandler errorHandler;
    
        @Override
        public void multicastEvent(ApplicationEvent event) {
            multicastEvent(event, resolveDefaultEventType(event));
        }
    
        @Override
        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);
                }
            }
        }
    
        @SuppressWarnings({"unchecked", "rawtypes"})
        protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
            ErrorHandler errorHandler = getErrorHandler();
            if (errorHandler != null) {
                try {
                    listener.onApplicationEvent(event);
                }
                catch (Throwable err) {
                }
            }
            else {
                try {
                    listener.onApplicationEvent(event);
                }
                catch (ClassCastException ex) {
                }
            }
        }
    }
    
    • SimpleApplicationEventMulticaster的multicastEvent负责同步或者多线程发布事件。
    • invokeListener支持同步或者多线程发布事件。
    • 广播过程中会通过getApplicationListeners(event, type)来获取该事件对象的listener。
    • SimpleApplicationEventMulticaster包含了所有的事件监听器,但是广播的时候需要根据事件类型找到对应的listener进行广播。
    public abstract class AbstractApplicationEventMulticaster
            implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
    
        private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
        final Map<ListenerCacheKey, ListenerRetriever> retrieverCache =
                new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);
        private ClassLoader beanClassLoader;
        private BeanFactory beanFactory;
        private Object retrievalMutex = this.defaultRetriever;
    
        @Override
        public void addApplicationListener(ApplicationListener<?> listener) {
            synchronized (this.retrievalMutex) {
                Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
                if (singletonTarget instanceof ApplicationListener) {
                    this.defaultRetriever.applicationListeners.remove(singletonTarget);
                }
                this.defaultRetriever.applicationListeners.add(listener);
                this.retrieverCache.clear();
            }
        }
    
        protected Collection<ApplicationListener<?>> getApplicationListeners(
                ApplicationEvent event, ResolvableType eventType) {
    
            Object source = event.getSource();
            Class<?> sourceType = (source != null ? source.getClass() : null);
            ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
    
            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)))) {
                synchronized (this.retrievalMutex) {
                    retriever = this.retrieverCache.get(cacheKey);
                    if (retriever != null) {
                        return retriever.getApplicationListeners();
                    }
                    retriever = new ListenerRetriever(true);
                    Collection<ApplicationListener<?>> listeners =
                            retrieveApplicationListeners(eventType, sourceType, retriever);
                    this.retrieverCache.put(cacheKey, retriever);
                    return listeners;
                }
            }
            else {
                return retrieveApplicationListeners(eventType, sourceType, null);
            }
        }
    
    
        private Collection<ApplicationListener<?>> retrieveApplicationListeners(
                ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) {
    
            LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
            Set<ApplicationListener<?>> listeners;
            Set<String> listenerBeans;
            synchronized (this.retrievalMutex) {
                listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
                listenerBeans = new LinkedHashSet<String>(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) {
                    }
                }
            }
            AnnotationAwareOrderComparator.sort(allListeners);
            return allListeners;
        }
    }
    
    • retrieveApplicationListeners根据EventType筛选Listener进行广播。

    相关文章

      网友评论

        本文标题:Spring事件监听详解

        本文链接:https://www.haomeiwen.com/subject/seqgvltx.html