Spring中的設計模式--觀察者模式

spring在容器中使用了觀察者模式:web

  1、spring事件:ApplicationEvent,該抽象類繼承了EventObject類,jdk建議全部的事件都應該繼承自EventObject。spring

  2、spring事件監聽器:ApplicationLisener,該接口繼承了EventListener接口,jdk建議全部的事件監聽器都應該繼承EventListener。緩存

Java代碼    收藏代碼
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {  
  
    /** 
     * Handle an application event. 
     * @param event the event to respond to 
     */  
    void onApplicationEvent(E event);    
} 

  3、spring事件發佈:ApplicationEventPublisher 。 ApplicationContext繼承了該接口,在ApplicationContext的抽象類AbstractApplicationContext中作了實現。數據結構

package org.springframework.context;

public interface ApplicationEventPublisher {
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an application event. Events may be framework events
* (such as RequestHandledEvent) or application-specific events.
* @param event the event to publish
* @see org.springframework.web.context.support.RequestHandledEvent
*/
  void publishEvent(ApplicationEvent var1);

    void publishEvent(Object var1);
}

 

 

  AbstractApplicationContext類中publishEvent方法實現: app

    /**
     * Publish the given event to all listeners.
     * <p>Note: Listeners get initialized after the MessageSource, to be able
     * to access it within listener implementations. Thus, MessageSource
     * implementations cannot publish events.
     * @param event the event to publish (may be an {@link ApplicationEvent}
     * or a payload object to be turned into a {@link PayloadApplicationEvent})
     */
    @Override
    public void publishEvent(Object event) {
        publishEvent(event, null);
    }

    /**
     * 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");
        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 = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
            }
        }

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

 

   由上代碼可知,AbstractApplicationContext類並無具體的作事件廣播,而是委託給ApplicationEventMulticaster來進行,ApplicationEventMulticaster的multicastEvent()方法實現以下:異步

    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            }
            else {
                invokeListener(listener, event);
            }
        }
    }
  protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
        ErrorHandler errorHandler = this.getErrorHandler();
        if (errorHandler != null) {
            try {
                listener.onApplicationEvent(event);
            } catch (Throwable var6) {
                errorHandler.handleError(var6);
            }
        } else {
            try {
                listener.onApplicationEvent(event);
            } catch (ClassCastException var5) {
                LogFactory.getLog(this.getClass()).debug("Non-matching event type for listener: " + listener, var5);
            }
        }

    }

 

 得到listener集合,遍歷listener觸發事件Executor接口有多個實現類,能夠支持同步或異步廣播事件。ide

 

問題:spring容器是怎麼根據事件去找到事件對應的事件監聽器呢?函數

 1、入口post

private ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:/spring/applicationContext.xml");

 2、生成Spring上下文ApplicationContext測試

   public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
        super(parent);
        this.setConfigLocations(configLocations);
        if (refresh) {
            this.refresh();
        }

    }

3、調用spring容器初始化方法

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();
    
            
                                //初始化一個事件註冊表
                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // 初始化事件監聽器
                // Check for listener beans and register them.
                registerListeners();
                // 實例化全部單例對象,其中包括默認註冊表
                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);
                // 發佈事件
                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }                                                      

 3.1 initApplicationEventMulticaster()方法代碼

   protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
     //先查找BeanFactory配置文件中是否有ApplicationEventMulticaster  
        if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
            this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        } else {// 若是beanFactory中沒有,則建立一個SimpleApplicationEventMulticaster
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [" + this.applicationEventMulticaster + "]");
            }
        }

    }

  spring先從beanFactory中獲取ApplicationEventMulticaster,若是沒有自定義,則建立一個SimpleApplicationEventMulticaster。 

 

ApplicationEventMulticaster包含如下屬性:defaultRetriever即爲註冊表,註冊監聽事件的相關消息; retrieverCache用來作defaultRetriever的緩存。 

public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
    private final AbstractApplicationEventMulticaster.ListenerRetriever defaultRetriever = new AbstractApplicationEventMulticaster.ListenerRetriever(false);
    final Map<AbstractApplicationEventMulticaster.ListenerCacheKey, AbstractApplicationEventMulticaster.ListenerRetriever> retrieverCache = new ConcurrentHashMap(64);
    private ClassLoader beanClassLoader;
    private BeanFactory beanFactory;
    private Object retrievalMutex;
}

 

 ListenerRetriever的數據結構以下:applicationListeners用來存放監聽事件, applicationListenerBeans爲存放監聽事件的類名稱。
private class ListenerRetriever {
        public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet();
        public final Set<String> applicationListenerBeans = new LinkedHashSet();
        private final boolean preFiltered;

 ListenerCacheKey的數據結構以下:eventType是事件類型,sourceType是事件的源類型,即爲事件的構造函數的參數類型。

   private static class ListenerCacheKey {
        private final ResolvableType eventType;
        private final Class<?> sourceType;

3.2 registerListeners()方法代碼

初始化註冊表之後,則把事件註冊到註冊表中,registerListeners()

  protected void registerListeners() {
     //獲取全部的listener的迭代器
        Iterator var1 = this.getApplicationListeners().iterator();

        while(var1.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var1.next();
            //把獲取全部的listener, 把事件的bean放到ApplicationEventMulticaster中的ApplicationListener
        this.getApplicationEventMulticaster().addApplicationListener(listener);
        }

        String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
        String[] var7 = listenerBeanNames;
        int var3 = listenerBeanNames.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String listenerBeanName = var7[var4];
          //把事件的名稱放到ApplicationListenerBean裏去   
      this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
} Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { Iterator var9 = earlyEventsToProcess.iterator(); while(var9.hasNext()) { ApplicationEvent earlyEvent = (ApplicationEvent)var9.next(); this.getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
3.3 finishBeanFactoryInitialization(beanFactory)

 具體會執行到下面的方法,會把AbstractApplicationEventMulticaster的defaultRetriever屬性賦值。

執行PostProcessorRegistrationDelegate類的postProcessAfterInitialization()方法:
 public Object postProcessAfterInitialization(Object bean, String beanName) {
            if (this.applicationContext != null && bean instanceof ApplicationListener) {
                Boolean flag = (Boolean)this.singletonNames.get(beanName);
                if (Boolean.TRUE.equals(flag)) {
                    this.applicationContext.addApplicationListener((ApplicationListener)bean);
                } else if (flag == null) {
                    if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
                        logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " + "but is not reachable for event multicasting by its containing ApplicationContext " + "because it does not have singleton scope. Only top-level listener beans are allowed " + "to be of non-singleton scope.");
                    }

                    this.singletonNames.put(beanName, Boolean.FALSE);
                }
            }

            return bean;
        }

   執行AbstractApplicationContext類的addApplicationListener()方法:

  public void addApplicationListener(ApplicationListener<?> listener) {
        if (this.applicationEventMulticaster != null) {
            this.applicationEventMulticaster.addApplicationListener(listener);
        } else {
            this.applicationListeners.add(listener);
        }
    }
  執行AbstractApplicationEventMulticaster類的addApplicationListener()方法
  public void addApplicationListener(ApplicationListener<?> listener) {
        Object var2 = this.retrievalMutex;
        synchronized(this.retrievalMutex) {
            this.defaultRetriever.applicationListeners.add(listener);
            this.retrieverCache.clear();
        }
   }

 

 

 【spring根據反射機制,經過方法getBeansOfType()獲取全部繼承了ApplicationListener接口的監聽器,而後把監聽器全放到註冊表裏,因此咱們能夠在spring配置文件中配置自定義的監聽器,在spring初始化的時候會把監聽器自動註冊到註冊表中。】

 

3.4 finishRefresh()
裏面執行發佈事件。
  protected void finishRefresh() {
        this.initLifecycleProcessor();
        this.getLifecycleProcessor().onRefresh();
        this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
        LiveBeansView.registerApplicationContext(this);
    }

 

在applicationContext發佈事件的時候。 

 public void publishEvent(ApplicationEvent event) {
        this.publishEvent(event, (ResolvableType)null);
    }

    public void publishEvent(Object event) {
        this.publishEvent(event, (ResolvableType)null);
    }

    protected void publishEvent(Object event, ResolvableType eventType) {
        Assert.notNull(event, "Event must not be null");
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Publishing event in " + this.getDisplayName() + ": " + event);
        }

        Object applicationEvent;
        if (event instanceof ApplicationEvent) {
            applicationEvent = (ApplicationEvent)event;
        } else {
            applicationEvent = new PayloadApplicationEvent(this, event);
            if (eventType == null) {
                eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
            }
        }

        if (this.earlyApplicationEvents != null) {
            this.earlyApplicationEvents.add(applicationEvent);
        } else {
      // 調用ApplicationEventMulticaster的multicastEvent()方法        
      this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
} if (this.parent != null) { if (this.parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext)this.parent).publishEvent(event, eventType); } else { this.parent.publishEvent(event); } } }

AbstractApplicationContext類並無具體的作事件廣播,而是委託給ApplicationEventMulticaster來進行。

 ApplicationEventMulticaster的方法multicastEvent()爲: 
 public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        Iterator var4 = this.getApplicationListeners(event, type).iterator();

        while(var4.hasNext()) {
            final ApplicationListener<?> listener = (ApplicationListener)var4.next();
            Executor executor = this.getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    public void run() {
                        SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
                    }
                });
            } else {
                this.invokeListener(listener, event);
            }
        }

    }

 

根據事件和類型獲取全部的監聽器方法: getApplicationListeners()
 protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
        Object source = event.getSource();
        Class<?> sourceType = source != null ? source.getClass() : null;
        AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
        AbstractApplicationEventMulticaster.ListenerRetriever retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
       //從緩存裏查找ListenerRetriever    
if (retriever != null) { return retriever.getApplicationListeners(); } else if (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) { Object var7 = this.retrievalMutex; synchronized(this.retrievalMutex) { retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } else {
            //若是緩存裏不存在,則去得到  retriever
= new AbstractApplicationEventMulticaster.ListenerRetriever(true); Collection<ApplicationListener<?>> listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } } else { return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null); } }

  

private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, Class<?> sourceType, AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
        LinkedList<ApplicationListener<?>> allListeners = new LinkedList();
        Object var7 = this.retrievalMutex;
        LinkedHashSet listeners;
        LinkedHashSet listenerBeans;
        synchronized(this.retrievalMutex) {
         //獲取註冊表裏全部的listener, defaultRetriever在前面已被賦值  listeners
= new LinkedHashSet(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans); } Iterator var14 = listeners.iterator(); while(var14.hasNext()) { ApplicationListener<?> listener = (ApplicationListener)var14.next();
       //根據事件類型,事件源類型,獲取所須要的監聽事件  
if (this.supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListeners.add(listener); } allListeners.add(listener); } } if (!listenerBeans.isEmpty()) { BeanFactory beanFactory = this.getBeanFactory(); Iterator var16 = listenerBeans.iterator(); while(var16.hasNext()) { String listenerBeanName = (String)var16.next(); try { Class<?> listenerType = beanFactory.getType(listenerBeanName); if (listenerType == null || this.supportsEvent(listenerType, eventType)) { ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class); if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListenerBeans.add(listenerBeanName); } allListeners.add(listener); } } } catch (NoSuchBeanDefinitionException var13) { ; } } } AnnotationAwareOrderComparator.sort(allListeners); return allListeners; }

 

 配合上面的註解,便可理解,根據事件和事件類型找到對應的監聽器,那麼如何根據事件類型找到對應的監聽器呢?

 上面方法中的supportsEvent(listener, eventType, sourceType)方法實現了根據事件類型查找對應的監聽器,代碼具體實現爲:

  protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) {
        GenericApplicationListener smartListener = listener instanceof GenericApplicationListener ? (GenericApplicationListener)listener : new GenericApplicationListenerAdapter(listener);
        return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType);
    }

 如上可知:上面方法的返回結果跟方法smartListener.supportsEventType(eventType)和smartListener.supportsSourceType(sourceType)有關。

smartListener.supportsEventType(eventType)方法實現爲:

public boolean supportsEventType(ResolvableType eventType) {
        if (this.delegate instanceof SmartApplicationListener) {
            Class<? extends ApplicationEvent> eventClass = eventType.getRawClass();
            return ((SmartApplicationListener)this.delegate).supportsEventType(eventClass);
        } else {
            return this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType);
        }
    }

  該方法主要的邏輯就是根據事件類型判斷是否和監聽器參數泛型的類型是否一致。 

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {  
  
    /** 
     * Handle an application event. 
     * @param event the event to respond to 
     */  
    void onApplicationEvent(E event);  
  
} 

 

 在定義本身的監聽器要明確指定參數泛型,代表該監聽器支持的事件,若是不指明具體的泛型,則沒有監聽器監聽事件。

smartListener.supportsSourceType(sourceType)方法的實現爲:

public boolean supportsSourceType(Class<?> sourceType) {
        return this.delegate instanceof SmartApplicationListener ? ((SmartApplicationListener)this.delegate).supportsSourceType(sourceType) : true;
    }

  以上是spring的事件體系。

 

 4、自定義事件和監聽器

咱們可使用spring的事件廣播體系,自定義本身的事件:

自定義事件,繼承ApplicationEvent:

public class DIYEvent extends ApplicationEvent {
    private static final long serialVersionUID = 7099057708183571977L;

    public DIYEvent(String source) {
        super(source);
    }
}

 

自定義listener,繼承ApplicationListener

@Component
public class DIYListener implements ApplicationListener<DIYEvent> {
    @Override
    public void onApplicationEvent(DIYEvent diyEvent) {
        System.out.println("自定義監聽器執行");
        System.out.println(diyEvent.getSource());
    }
}

 

測試觸發事件:

public class DIYTest{
    private ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:/spring/applicationContext.xml");

    @Test
    public void diyTest(){
        applicationContext.publishEvent(new DIYEvent("測試數據"));
    }
}

  獲取ApplicationContext,發佈事件。

 

調試結果:

自定義監聽器執行
測試數據
相關文章
相關標籤/搜索