Spring中的事件驅動模型(一)

事件驅動模型簡介

事件驅動模型一般也被理解成觀察者或者發佈/訂閱模型。java

  • 是一種對象間的一對多的關係;
  • 當目標發送改變(發佈),觀察者(訂閱者)就能夠接收到改變;
  • 觀察者如何處理,目標無需干涉,它們之間的關係是鬆耦合的。

event-source
事件驅動模型

事件驅動模型的例子不少,如生活中的紅綠燈,以及咱們在微服務中用到的配置中心,當有配置提交時出發具體的應用實例更新Spring上下文環境。web

Spring的事件機制

基本概念

Spring的事件驅動模型由三部分組成:微信

  • 事件:ApplicationEvent,繼承自JDK的EventObject,全部事件將繼承它,並經過source獲得事件源。
  • 事件發佈者:ApplicationEventPublisher及ApplicationEventMulticaster接口,使用這個接口,咱們的Service就擁有了發佈事件的能力。
  • 事件訂閱者:ApplicationListener,繼承自JDK的EventListener,全部監聽器將繼承它。

Spring事件驅動過程

事件

Spring 默認對 ApplicationEvent 事件提供了以下實現:框架

  • ContextStoppedEvent:ApplicationContext中止後觸發的事件;
  • ContextRefreshedEvent:ApplicationContext初始化或刷新完成後觸發的事件;
  • ContextClosedEvent:ApplicationContext關閉後觸發的事件。如web容器關閉時自動會觸發Spring容器的關閉,若是是普通java應用,須要調用ctx.registerShutdownHook()註冊虛擬機關閉時的鉤子才行;
  • ContextStartedEvent:ApplicationContext啓動後觸發的事件;

eventobject
事件

public abstract class ApplicationEvent extends EventObject {
    private static final long serialVersionUID = 7099057708183571937L;
    //事件發生的時間
    private final long timestamp = System.currentTimeMillis();
	//建立一個新的ApplicationEvent事件
    public ApplicationEvent(Object source) {
        super(source);
    }

    public final long getTimestamp() {
        return this.timestamp;
    }
}
複製代碼

事件基類ApplicationEvent,全部的具體事件都會繼承該抽象事件類。異步

事件監聽者

ApplicationListener
事件監聽
ApplicationListener繼承自JDK的 EventListener,JDK要求全部監聽器將繼承它。

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    void onApplicationEvent(E var1);
}
複製代碼

提供了onApplicationEvent方法,用以處理ApplicationEvent,不過對於具體事件的處理須要進行判斷。而GenericApplicationListenerSmartApplicationListener提供了關於事件更多的元數據信息。ide

public class SourceFilteringListener implements GenericApplicationListener, SmartApplicationListener {

	private final Object source;

	@Nullable
	private GenericApplicationListener delegate;

	//爲特定事件源建立SourceFilteringListener,並傳入代理的監聽器類
	public SourceFilteringListener(Object source, ApplicationListener<?> delegate) {
		this.source = source;
		this.delegate = (delegate instanceof GenericApplicationListener ?
				(GenericApplicationListener) delegate : new GenericApplicationListenerAdapter(delegate));
	}
	//....省略部分代碼
	
	@Override
	public int getOrder() {
		return (this.delegate != null ? this.delegate.getOrder() : Ordered.LOWEST_PRECEDENCE);
	}

	//過濾以後實際處理事件
	protected void onApplicationEventInternal(ApplicationEvent event) {
		//...
		this.delegate.onApplicationEvent(event);
	}

}
複製代碼

SourceFilteringListenerApplicationListener的裝飾器類,過濾特定的事件源。只會注入其事件對應的代理監聽器,還提供了按照順序觸發監聽器等功能。 在啓動的時候會加載一部分 ApplicationListener。Spring Context加載初始化完成(refresh)後會再次檢測應用中的 ApplicationListener,而且註冊,此時會將咱們實現的 ApplicationListener 就會加入到 SimpleApplicationEventMulticaster 維護的 Listener 集合中。 Spring也支持直接註解的形式進行事件監聽@EventListener(Event.class)微服務

事件發佈

EventPublisher
發佈事件
ApplicationContext接口繼承了 ApplicationEventPublisher,並在 AbstractApplicationContext實現了具體代碼,實際執行是委託給 ApplicationEventMulticaster

@FunctionalInterface
public interface ApplicationEventPublisher {
	//通知全部的註冊該事件的應用,事件能夠是框架事件如RequestHandledEvent或者特定的應用事件。
    default void publishEvent(ApplicationEvent event) {
        this.publishEvent((Object)event);
    }

    void publishEvent(Object var1);
}
複製代碼

實際的執行是委託給,讀者有興趣能夠看一下AbstractApplicationContext中這部分的邏輯。下面咱們具體看一下ApplicationEventMulticaster接口中定義的方法。源碼分析

public interface ApplicationEventMulticaster {

	//增長監聽者
	void addApplicationListener(ApplicationListener<?> listener);
	//...

	//移除監聽者
	void removeApplicationListener(ApplicationListener<?> listener);
	//...
	
	//廣播特定事件給監聽者
	void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);

}
複製代碼

AbstractApplicationContext中定義了對監聽者的操做維護,如增長和刪除,並提供了將特定事件進行廣播的方法。下面看一下具體實現類SimpleApplicationEventMulticasterApplicationContext自動到本地容器裏找一個ApplicationEventMulticaster實現,若是沒有則會使用默認的SimpleApplicationEventMulticasterthis

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

	@Nullable
	private Executor taskExecutor;

	//...
	
	//用給定的beanFactory建立SimpleApplicationEventMulticaster
	public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
		setBeanFactory(beanFactory);
	}

	@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 = getErrorHandler();
		if (errorHandler != null) {
			try {
				doInvokeListener(listener, event);
			}
			...
		}
		else {
			doInvokeListener(listener, event);
		}
	}

	@SuppressWarnings({"unchecked", "rawtypes"})
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			listener.onApplicationEvent(event);
		}
		//...
	}

}
複製代碼

multicastEvent方法中,executor不爲空的狀況下,能夠看到是支持異步發佈事件。發佈事件時只須要調用ApplicationContext中的publishEvent方法便可進行事件的發佈。spa

總結

本文主要介紹了Spring中的事件驅動模型相關概念。首先介紹事件驅動模型,也能夠說是觀察者模式,在咱們的平常生活中和應用開發中有不少應用。隨後重點篇幅介紹了Spring的事件機制,Spring的事件驅動模型由事件、發佈者和訂閱者三部分組成,結合Spring的源碼分析了這三部分的定義與實現。筆者將會在下一篇文章,結合具體例子以及Spring Cloud Config中的實現進行實戰講解。

訂閱最新文章,歡迎關注個人公衆號

微信公衆號

參考

  1. 事件驅動模型簡介
  2. Spring事件驅動模型與觀察者模式
相關文章
相關標籤/搜索