spring源碼分析系列 (15) 設計模式解析


 spring是目前使用最為廣泛的Java框架之一。雖然spring最為核心是IOC和AOP,其中代碼實現中很多設計模式得以應用,代碼看起來簡潔流暢,在日常的軟件設計中很值得借鑒。以下是對一些設計模式的理解以及源碼解析,希望能給大家對設計模式的理解有所幫助。

 

  1. 觀察者模式:發布/訂閱

 

更多設計模式更新中.....

(基於spring-4.3.23.RELEASE分析)  

 

1、觀察者模式: 發布/訂閱

如對觀察者模式還不是很有概念,可以點擊這里。spring中ApplicationEvent事件通知就是觀察者模式的變種,巧妙的利用事件驅動機制實現容器刷新。開發者可充分利用該機制,實現框架的深度定制。下面分為幾點展開:

 

(a) spring中實現觀察者模式的各個角色:

 ApplicationEventMulticaster是一個接口,定義了事件管理的基本行為,目前spring只有一個實現類和一個抽象類。這里先貼出定義理解各個角色的作用,后邊一點點串聯整個功能。

public interface ApplicationEventMulticaster {
    /**
     * 增加一個具體事件監聽器
     */
    void addApplicationListener(ApplicationListener<?> listener);
    /**
     * 增加一個事件監聽器 以beanName形式 
     */
    void addApplicationListenerBean(String listenerBeanName);
    /**
     * 刪除一個具體事件監聽器
     */
    void removeApplicationListener(ApplicationListener<?> listener);
    /**
     * 刪除一個事件監聽器 以beanName形式 
     */
    void removeApplicationListenerBean(String listenerBeanName);
    /**
     * 刪除所有事件監聽器 
     */
    void removeAllListeners();
    /**
     * 發布事件
     */
    void multicastEvent(ApplicationEvent event);
    /**
     * 發布事件
     */
    void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}

 ApplicationEvent是事件通知的媒介,也是消息傳遞的載體。這個類只是繼承JDK原生的EventObject,約定為source的事件傳遞數據 只要理解其作用即可 比較簡單所以貼出代碼

/**
 * Class to be extended by all application events. Abstract as it
 * doesn't make sense for generic events to be published directly.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 */
public abstract class ApplicationEvent extends EventObject {

    /** use serialVersionUID from Spring 1.2 for interoperability. */
    private static final long serialVersionUID = 7099057708183571937L;

    /** System time when the event happened. */
    private final long timestamp;


    /**
     * Create a new ApplicationEvent.
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }


    /**
     * Return the system time in milliseconds when the event happened.
     */
    public final long getTimestamp() {
        return this.timestamp;
    }

}
ApplicationEvent.java
/**
 * <p>
 * The root class from which all event state objects shall be derived.
 * <p>
 * All Events are constructed with a reference to the object, the "source",
 * that is logically deemed to be the object upon which the Event in question
 * initially occurred upon.
 *
 * @since JDK1.1
 */

public class EventObject implements java.io.Serializable {

    private static final long serialVersionUID = 5516075349620653480L;

    /**
     * The object on which the Event initially occurred.
     */
    protected transient Object  source;

    /**
     * Constructs a prototypical Event.
     *
     * @param    source    The object on which the Event initially occurred.
     * @exception  IllegalArgumentException  if source is null.
     */
    public EventObject(Object source) {
        if (source == null)
            throw new IllegalArgumentException("null source");

        this.source = source;
    }

    /**
     * The object on which the Event initially occurred.
     *
     * @return   The object on which the Event initially occurred.
     */
    public Object getSource() {
        return source;
    }

    /**
     * Returns a String representation of this EventObject.
     *
     * @return  A a String representation of this EventObject.
     */
    public String toString() {
        return getClass().getName() + "[source=" + source + "]";
    }
}
EventObject.java

ApplicationEventPublisher是對外暴露發布事件接口的定義 ApplicationContext容器實現該接口定義:

/**
 * Interface that encapsulates event publication functionality.
 * Serves as super-interface for {@link ApplicationContext}.
 *
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @since 1.1.1
 * @see ApplicationContext
 * @see ApplicationEventPublisherAware
 * @see org.springframework.context.ApplicationEvent
 * @see org.springframework.context.event.EventPublicationInterceptor
 */
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 event);

    /**
     * Notify all <strong>matching</strong> listeners registered with this
     * application of an event.
     * <p>If the specified {@code event} is not an {@link ApplicationEvent},
     * it is wrapped in a {@link PayloadApplicationEvent}.
     * @param event the event to publish
     * @since 4.2
     * @see PayloadApplicationEvent
     */
    void publishEvent(Object event);

}
ApplicationEventPublisher.java

 SimpleApplicationEventMulticaster是AbstractApplicationEventMulticaster具體的實現,可以配置異步調用以解決效率問題以及事件調用異常的處理方式。主要的邏輯不復雜,很多實現的細節都隱藏在抽象類中,后續會有分析,很容易看得懂 接下來把目光聚集在AbstractApplicationEventMulticaster類。

 AbstractApplicationEventMulticaster抽象類是分析的重點,該類實現了大部分的核心功能,包括監聽者增加、刪除、根據發布的事件類型匹配監聽者,下面將結合容器刷新來串聯整個過程。

 

(b) 容器刷新中使用到的事件機制。

(1)、AbstractApplicationContext中refresh()是整個spring容器刷新的入口, 如果你看過spring源碼肯定非常熟悉這段代碼:

@Override
public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // 獲取容器,具體實現類重載加載所有bean定義
            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();

                // 初始化事件廣播器 即上文的SimpleApplicationEventMulticaster 也可以重載該方法,注冊自定義的廣播器,實現定制化
 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
                onRefresh();

                // 開始注冊監聽器
 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // 完成最后容器工作 發布第一個容器刷新完成事件
 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();
            }
        }
    }

 (2) 、跟蹤initApplicationEventMulticaster()方法可以看出來,如果手動注入name為“applicationEventMulticaster”的bean 則spring會使用定制化的事件廣播器,否則會默認使用SimpleApplicationEventMulticaster。

/**
     * Name of the ApplicationEventMulticaster bean in the factory.
     * If none is supplied, a default SimpleApplicationEventMulticaster is used.
     * @see org.springframework.context.event.ApplicationEventMulticaster
     * @see org.springframework.context.event.SimpleApplicationEventMulticaster
     */
    public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";


   /**
     * Initialize the ApplicationEventMulticaster.
     * Uses SimpleApplicationEventMulticaster if none defined in the context.
     * @see org.springframework.context.event.SimpleApplicationEventMulticaster
     */
    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);
            if (logger.isTraceEnabled()) {
                logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isTraceEnabled()) {
                logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                        "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
            }
        }
    }
initApplicationEventMulticaster()

 (3)、 此時事件廣播器已經注冊,再跟蹤registerListeners()方法。 該方法主要完成所有監聽者的注冊、 觸發最早起的事件通知,也是spring容器刷新階段較早期觸發的事件。

   /**
     * 注冊所有的監聽器 
     */
    protected void registerListeners() {
        // Register statically specified listeners first.
        // 注冊容器創建時期靜態賦值的監聽器
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let post-processors apply to them!
        // 獲取所有監聽器的bean name 並注冊所有beanName 以待后續查找使用
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // Publish early application events now that we finally have a multicaster...
        // 觸發最早起的事件通知 並且只會觸發一次
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

 (4)、跟蹤AbstractApplicationEventMulticaster#addApplicationListener 和  AbstractApplicationEventMulticaster#addApplicationListenerBean。 兩個方法都比較簡單,都是往監聽器持有者defaultRetriever注冊。

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) {
            // 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();
        }
    }
    
    //.........
}
View Code 

(5)、再分析最關鍵的SimpleApplicationEventMulticaster#multicastEvent(final ApplicationEvent event, ResolvableType eventType) 根據發布的事件類別找到匹配的ApplicationListener集合,並觸發通知。 串聯了整個事件通知流程: 

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) {
        // 使用spring提供的ResolvableType類型解析類 匹配發布事件類型獲得對應的監聽器 
        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);
            }
        }
    }

    private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
        return ResolvableType.forInstance(event);
    }

    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            }
            catch (Throwable err) {
                errorHandler.handleError(err);
            }
        }
        else {
            doInvokeListener(listener, event);
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    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.isDebugEnabled()) {
                    logger.debug("Non-matching event type for listener: " + listener, ex);
                }
            }
            else {
                throw ex;
            }
        }
    }

    private boolean matchesClassCastMessage(String classCastMessage, Class<?> eventClass) {
        // On Java 8, the message starts with the class name: "java.lang.String cannot be cast..."
        if (classCastMessage.startsWith(eventClass.getName())) {
            return true;
        }
        // On Java 11, the message starts with "class ..." a.k.a. Class.toString()
        if (classCastMessage.startsWith(eventClass.toString())) {
            return true;
        }
        // On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
        int moduleSeparatorIndex = classCastMessage.indexOf('/');
        if (moduleSeparatorIndex != -1 && classCastMessage.startsWith(eventClass.getName(), moduleSeparatorIndex + 1)) {
            return true;
        }
        // Assuming an unrelated class cast failure...
        return false;
    }

}
View Code

跟進AbstractApplicationEventMulticaster#getApplicationListeners(ApplicationEvent event, ResolvableType eventType)獲取所有符合條件的監聽器,涉及到spring的ResolvableType類型可以 點擊這里 進行詳細了解。

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;
    
    // 。。。。。。。。。

    /**
     * 根據事件類型找到匹配的監聽器集合 充分緩存機制解決效率問題
     *
     * Return a Collection of ApplicationListeners matching the given
     * event type. Non-matching listeners get excluded early.
     * @param event the event to be propagated. Allows for excluding
     * non-matching listeners early, based on cached matching information.
     * @param eventType the event type
     * @return a Collection of ApplicationListeners
     * @see org.springframework.context.ApplicationListener
     */
    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);

        // 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<ApplicationListener<?>> listeners =
                        retrieveApplicationListeners(eventType, sourceType, retriever);
                this.retrieverCache.put(cacheKey, retriever);
                return listeners;
            }
        }
        else {
            // No ListenerRetriever caching -> no synchronization necessary
            return retrieveApplicationListeners(eventType, sourceType, null);
        }
    }

    /**
     *  實際的事件類解析邏輯 結合上文提到的監聽器持有者defaultRetriever  使用spring提供的ResolvableType類進行類型匹配
     *  最后找到符合條件的監聽器
     * Actually retrieve the application listeners for the given event and source type.
     * @param eventType the event type
     * @param sourceType the event source type
     * @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)
     * @return the pre-filtered list of application listeners for the given event and source type
     */
    private Collection<ApplicationListener<?>> retrieveApplicationListeners(
            ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) {

        List<ApplicationListener<?>> allListeners = new ArrayList<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) {
                    // Singleton listener instance (without backing bean definition) disappeared -
                    // probably in the middle of the destruction phase
                }
            }
        }
        AnnotationAwareOrderComparator.sort(allListeners);
        return allListeners;
    }

    
    protected boolean supportsEvent(Class<?> listenerType, ResolvableType eventType) {
        if (GenericApplicationListener.class.isAssignableFrom(listenerType) ||
                SmartApplicationListener.class.isAssignableFrom(listenerType)) {
            return true;
        }
        ResolvableType declaredEventType = GenericApplicationListenerAdapter.resolveDeclaredEventType(listenerType);
        return (declaredEventType == null || declaredEventType.isAssignableFrom(eventType));
    }
    
    protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) {
        GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
                (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
        return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
    }


    /**
     * Cache key for ListenerRetrievers, based on event type and source type.
     */
    private static final class ListenerCacheKey implements Comparable<ListenerCacheKey> {

        private final ResolvableType eventType;

        private final Class<?> sourceType;

        public ListenerCacheKey(ResolvableType eventType, Class<?> sourceType) {
            this.eventType = eventType;
            this.sourceType = sourceType;
        }

        // .......
    }

    /**
     * 監聽器持有者 實際從bean容器獲得監聽器的bean實例 
     * Helper class that encapsulates a specific set of target listeners,
     * allowing for efficient retrieval of pre-filtered listeners.
     * <p>An instance of this helper gets cached per event type and source type.
     */
    private class ListenerRetriever {

        public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();

        public final Set<String> applicationListenerBeans = new LinkedHashSet<String>();

        private final boolean preFiltered;

        public ListenerRetriever(boolean preFiltered) {
            this.preFiltered = preFiltered;
        }

        public Collection<ApplicationListener<?>> getApplicationListeners() {
            List<ApplicationListener<?>> allListeners = new ArrayList<ApplicationListener<?>>(
                    this.applicationListeners.size() + this.applicationListenerBeans.size());
            allListeners.addAll(this.applicationListeners);
            if (!this.applicationListenerBeans.isEmpty()) {
                BeanFactory beanFactory = getBeanFactory();
                for (String listenerBeanName : this.applicationListenerBeans) {
                    try {
                        ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                        if (this.preFiltered || !allListeners.contains(listener)) {
                            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;
        }
    }

}
AbstractApplicationEventMulticaster.java

 

(6)、最后finishRefresh()發布容器刷新成功事件

/**
     * Finish the refresh of this context, invoking the LifecycleProcessor's
     * onRefresh() method and publishing the
     * {@link org.springframework.context.event.ContextRefreshedEvent}.
     */
    protected void finishRefresh() {
        // Initialize lifecycle processor for this context.
        initLifecycleProcessor();

        // Propagate refresh to lifecycle processor first.
        getLifecycleProcessor().onRefresh();

        // Publish the final event.
        // 發布容器刷新成功事件
        publishEvent(new ContextRefreshedEvent(this));

        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
    }
View Code

(7)、跟蹤上述的publishEvent(Object event, ResolvableType eventType)方法, spring容器實現了ApplicationEventPublisher接口 並委托事件廣播器AbstractApplicationEventMulticaster完成事件到發布的過程。

    // 發布一個 ApplicationEvent 事件
    @Override
    public void publishEvent(ApplicationEvent event) {
        publishEvent(event, null);
    }

    // 發布一個ApplicationEvent事件 如果非ApplicationEvent類型事件,則默認被封裝成PayloadApplicationEvent事件 傳遞實體
    @Override
    public void publishEvent(Object 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類型事件,則默認被封裝成PayloadApplicationEvent事件 傳遞實體
        ApplicationEvent applicationEvent;
        if (event instanceof ApplicationEvent) {
            applicationEvent = (ApplicationEvent) event;
        }
        else {
            applicationEvent = new PayloadApplicationEvent<Object>(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 {
            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);
            }
        }
    }

 

源碼分析到這里基本串聯了整個流程,用一張圖說明容器刷新時候事件調用鏈圖,展示整個過程的數據流:

 

 

(c) 依據spring機制實現事件的發布/訂閱 定制化框架。

實際項目中會有一些定制化的需求,spring強大之處不僅僅是Bean的托管,還提供很多拓展機制,例如Bean生命周期各個的接口 點擊這里了解更多,還有本文的主題ApplicationEvent發布特定的事件機制定制化框架。常見的spring內嵌Tomcat等Servlet容器提供Http服務 則優雅down機器很重要,需要等待所有業務請求處理完畢再關閉容器。 下面是一個簡單的demo,也是拓展事件機制的基礎:

 實際傳遞DTO

@Data
@AllArgsConstructor
@ToString
public class EventDto {
    private String name ;
}

 發布的事件繼承自 ApplicationEvent

@Getter
public class DemoApplicationEvent extends ApplicationEvent {
    private String demo ;
    public DemoApplicationEvent(String demo, EventDto eventDto) {
        super(eventDto);
        this.demo = demo ;
    }
}

 事件監聽者

@Component
public class DemoApplicationListener implements ApplicationListener<DemoApplicationEvent> {
    /**
     * Handle an application event.
     *
     * @param event the event to respond to
     */
    @Override
    public void onApplicationEvent(DemoApplicationEvent event) {
        System.out.println(event.getDemo() + " -- " + event.getSource());
    }
}

 啟動springboot:

@SpringBootApplication
public class MqStarterApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(MqStarterApplication.class, args);
        ctx.publishEvent(new DemoApplicationEvent("hello", new EventDto("pig")));
    }
}

 運行結果:

hello -- EventDto(name=pig)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM