エレガントなプログラミング - SpringEvent

SpringEventイベント駆動型の導入

イベントプロトタイプ、イベント発行、イベントリスナー:イベント駆動型モデルでは春にもパブリッシュ・サブスクライブ・モデルとして知られている、典型的なSpringアプリケーションのイベント駆動型モデルのオブザーバ・モードの3つの役割の存在があります。

春のイベントプロトタイプ

春のイベントは、ApplicationEventによって定義されたEVENTOBJECTのJDKからクラス継承され; JDKは、このような私たちのAWTイベントシステムとして、すべてのイベントがそれを継承し、ソースでイベントソースを取得することが必要ですが、それから継承されます。

次のようにApplicationEvent仕様が定義されています。

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;
	}
}
复制代码

春のイベント出版社

春のイベントは、主にイベントを発行するイベント発行者のために、ApplicationEventPublisherで定義された仕様を公開します。

次のようにApplicationEventPublisher仕様が定義されています。

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);
}
复制代码

示されるようにApplicationContextのインターフェースは、ApplicationEventPublisher一体化されています。

画像

ApplicationContextのために、春には、デフォルトの実装を提供し、共通の抽象クラスAbstractApplicationContextでAnnotationConfigWebApplicationContextClassPathXmlApplicationContextFileSystemXmlApplicationContextイベントの行動AbstractApplicationContextを継承しています:

AbstractApplicationContextクラスコードは次のとおりです。

/**
 * 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, 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<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);
        }
    }
}
复制代码

この方法では、我々はgetApplicationEventMulticaster()を参照してください。ApplicationEventMulticasterは、イベントの放送局に属し、その役割はApplicationContextのは、すべてのリスナーにイベントの放送をリリースしています。

春のイベントリスナー

春ApplicationListenerは、次のように定義され、それらの規範を監視イベントに定義されています。

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

ApplicationListenerイベントリスナーからのすべてのリスナーは、このインタフェースを実装する必要があり、このインターフェースは、本体のみのプロセスのパラメータとしてApplicationEventまたはサブクラスオブジェクトを受け取りonApplicationEvent()メソッドは、イベントに基づいて異なっていてもよく、されているJDK継承適切な治療を判断。すべてのリスナーは、あなたが要件を持っている必要がある場合、あなたはこのインターフェイスのサブインターフェイスSmartApplicationListenerを実装することができ、あなたはこのインタフェースを介してリスナーを指定することができますメッセージが表示されますイベントトリガは、リスナーの注文を受け、一連のイベントを受け取ります。

次のようにインターフェイスは関係SmartApplicationListenerを統合しました:

画像

SpringEventイベント応用例

イベント定義

public class PlanAllocatePubEvent extends ApplicationEvent {

    public PlanAllocatePubEvent(Long allocateId) {
        super(allocateId);
    }
}
复制代码

イベント・パブリッシング

@Component
public class PlanAllocatePubPublisher {

    private static final Logger LOG = LoggerFactory.getLogger(PlanAllocatePubPublisher.class);

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void publishEvent(long allocateId){
        LOG.info("[事件发布] 数据创建, 编号:" + allocateId);
        PlanAllocatePubEvent event = new PlanAllocatePubEvent(allocateId);
        applicationEventPublisher.publishEvent(event);
    }
}
复制代码

イベントリスナー(障害)

同期イベント処理

@Component
public class SyncPlanAllocatePubListener implements ApplicationListener<PlanAllocatePubEvent>{

    private static final Logger LOG = LoggerFactory.getLogger(SyncPlanAllocatePubListener.class);

    @Override
    public void onApplicationEvent(PlanAllocatePubEvent planAllocatePubEvent) {
        LOG.info("[同步][事件监听][开始]数据创建, 数据编号:" + planAllocatePubEvent.getSource());
        doSomething();
        LOG.info("[同步][事件监听][结束]数据创建, 数据编号:" + planAllocatePubEvent.getSource());
    }

    public void doSomething(){
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }

}
复制代码

非同期イベント処理

@Component
@EnableAsync
public class AsynPlanAllocatePubListener implements ApplicationListener<PlanAllocatePubEvent> {

    private static final Logger LOG = LoggerFactory.getLogger(AsynPlanAllocatePubListener.class);

    @Async
    @Override
    public void onApplicationEvent(PlanAllocatePubEvent planAllocatePubEvent) {
        LOG.info("[异步][事件监听][开始]数据创建, 数据编号:" + planAllocatePubEvent.getSource());
        doSomething();
        LOG.info("[异步][事件监听][结束]数据创建, 数据编号:" + planAllocatePubEvent.getSource());
    }

    public void doSomething(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }

}
复制代码

イベントリスナー(注文)

サンプルコード:イベントリスナーロジック1

@Component
public class Order1PlanAllocatePubListener implements SmartApplicationListener {

    private static final Logger LOG = LoggerFactory.getLogger(Order1PlanAllocatePubListener.class);

    /**
     * supportsEventType用于指定支持的事件类型,只有支持的才调用onApplicationEvent
     * @param eventType
     * @return
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return eventType == PlanAllocatePubEvent.class;
    }

    /**
     * supportsSourceType支持的目标类型,只有支持的才调用onApplicationEvent
     * @param sourceType
     * @return
     */
    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return sourceType == Long.class;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        LOG.info("[有序事件][事件监听][Order:1]数据创建, 编号:" + event.getSource());
        doSomething();
    }

    /**
     * 优先级顺序,越小优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 1;
    }

    public void doSomething(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }
}
复制代码

サンプルコード:イベントリスナーロジック2

@Component
public class Order2PlanAllocatePubListener implements SmartApplicationListener{

    private static final Logger LOG =  LoggerFactory.getLogger(Order2PlanAllocatePubListener.class);

    /**
     * supportsEventType用于指定支持的事件类型,只有支持的才调用onApplicationEvent
     * @param eventType
     * @return
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return eventType == PlanAllocatePubEvent.class;
    }

    /**
     * supportsSourceType支持的目标类型,只有支持的才调用onApplicationEvent
     * @param sourceType
     * @return
     */
    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return sourceType == Long.class;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        LOG.info("[有序事件][事件监听][Order:2]数据创建, 编号:" + event.getSource());
        doSomething();
    }

    /**
     * 优先级顺序,越小优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 2;
    }

    public void doSomething(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }
}
复制代码

テストイベント


@Controller
@RequestMapping(value = "/api/event")
public class ApiPluginEventController {

    @Autowired
    private PlanAllocatePubPublisher planAllocatePubPublisher;

    @ResponseBody
    @GetMapping(value = "/publish")
    public Map pubEvent() throws Exception {
        for(int i=1; i<5; i++){
            planAllocatePubPublisher.publishEvent(i);
        }
        return ImmutableMap.builder().put("message", "ok").build();
    }
}
复制代码
非同期イベントの結果
INFO:2017-09-11 20:14:08.799[publishEvent] [事件发布] 数据创建, 数据编号:1 
INFO:2017-09-11 20:14:08.803[publishEvent] [事件发布] 数据创建, 数据编号:2 
INFO:2017-09-11 20:14:08.803[onApplicationEvent] [异步][事件监听][开始]数据创建, 数据编号:1 
INFO:2017-09-11 20:14:08.804[publishEvent] [事件发布] 数据创建, 数据编号:3 
INFO:2017-09-11 20:14:08.804[onApplicationEvent] [异步][事件监听][开始]数据创建, 数据编号:2 
INFO:2017-09-11 20:14:08.805[onApplicationEvent] [异步][事件监听][开始]数据创建, 数据编号:3 
INFO:2017-09-11 20:14:08.804[publishEvent] [事件发布] 数据创建, 数据编号4 
INFO:2017-09-11 20:14:08.805[onApplicationEvent] [异步][事件监听][开始]数据创建, 数据编号:4 
INFO:2017-09-11 20:14:11.807[onApplicationEvent] [异步][事件监听][结束]数据创建, 数据编号:1 
INFO:2017-09-11 20:14:11.807[onApplicationEvent] [异步][事件监听][结束]数据创建, 数据编号:2 
INFO:2017-09-11 20:14:11.807[onApplicationEvent] [异步][事件监听][结束]数据创建, 数据编号:3 
INFO:2017-09-11 20:14:11.809[onApplicationEvent] [异步][事件监听][结束]数据创建, 数据编号:4 
复制代码
同期イベントの結果
INFO:2017-09-11 20:17:07.470[publishEvent] [事件发布] 数据创建, 数据编号:1 
INFO:2017-09-11 20:17:07.473[onApplicationEvent] [同步][事件监听][开始]数据创建, 数据编号:1 
INFO:2017-09-11 20:17:09.476[onApplicationEvent] [同步][事件监听][结束]数据创建, 数据编号:1 
INFO:2017-09-11 20:17:09.477[publishEvent] [事件发布] 数据创建, 数据编号:2 
INFO:2017-09-11 20:17:09.478[onApplicationEvent] [同步][事件监听][开始]数据创建, 数据编号:2 
INFO:2017-09-11 20:17:11.481[onApplicationEvent] [同步][事件监听][结束]数据创建, 数据编号:2 
INFO:2017-09-11 20:17:11.481[publishEvent] [事件发布] 数据创建, 数据编号:3 
INFO:2017-09-11 20:17:11.482[onApplicationEvent] [同步][事件监听][开始]数据创建, 数据编号:3 
INFO:2017-09-11 20:17:13.486[onApplicationEvent] [同步][事件监听][结束]数据创建, 数据编号:3 
INFO:2017-09-11 20:17:13.487[publishEvent] [事件发布] 数据创建, 数据编号:4 
INFO:2017-09-11 20:17:13.487[onApplicationEvent] [同步][事件监听][开始]数据创建, 数据编号:4 
INFO:2017-09-11 20:17:15.492[onApplicationEvent] [同步][事件监听][结束]数据创建, 数据编号:4 
复制代码
注文したイベントの実行結果
INFO:2017-09-11 20:33:12.139[publishEvent] [事件发布] 数据创建, 编号:1 
INFO:2017-09-11 20:33:12.140[onApplicationEvent] [有序事件][事件监听][Order:1]数据创建, 编号:1 
INFO:2017-09-11 20:33:15.145[onApplicationEvent] [有序事件][事件监听][Order:2]数据创建, 编号:1 
INFO:2017-09-11 20:33:18.146[publishEvent] [事件发布] 数据创建, 编号:2 
INFO:2017-09-11 20:33:18.147[onApplicationEvent] [有序事件][事件监听][Order:1]数据创建, 编号:2 
INFO:2017-09-11 20:33:21.151[onApplicationEvent] [有序事件][事件监听][Order:2]数据创建, 编号:2 
INFO:2017-09-11 20:33:24.156[publishEvent] [事件发布] 数据创建, 编号:3 
INFO:2017-09-11 20:33:24.157[onApplicationEvent] [有序事件][事件监听][Order:1]数据创建, 编号:3 
INFO:2017-09-11 20:33:27.162[onApplicationEvent] [有序事件][事件监听][Order:2]数据创建, 编号:3 
INFO:2017-09-11 20:33:30.167[publishEvent] [事件发布] 数据创建, 编号:4 
INFO:2017-09-11 20:33:30.168[onApplicationEvent] [有序事件][事件监听][Order:1]数据创建, 编号:4 
INFO:2017-09-11 20:33:33.171[onApplicationEvent] [有序事件][事件监听][Order:2]数据创建, 编号:4 
复制代码

ノートイベントリスナ

Spring4.2はApplicationListenerインタフェースを実装するために、リスナーはもはや必要性を作り、唯一の方法は、必ずしもonApplicationEvent呼び出されない、モニタ法上のコメントに追加する必要がありますが、唯一つのパラメータ、指定されたリスナーがある、@EventListenerノートの提供を開始しました。イベント型ロジックは、注釈の方法を使用することができ、上記の例では、イベントリスナーを命じました。

@Component
public class PlanAllocatePubHandler {

    private static final Logger LOG = LoggerFactory.getLogger(PlanAllocatePubHandler.class);

    /**
     * 基于注解的事件监听
     * @param planAllocatePubEvent
     */
    @EventListener
    @Order(1)
    public void annoEnvListener1(PlanAllocatePubEvent planAllocatePubEvent) {
        LOG.info("[注解事件监听][Order:1]数据创建, 编号:" + planAllocatePubEvent.getSource());
        doSomething();
    }

    /**
     * 基于注解的事件监听
     * @param planAllocatePubEvent
     */
    @EventListener
    @Order(2)
    public void annoEnvListener2(PlanAllocatePubEvent planAllocatePubEvent) {
        LOG.info("[注解事件监听][Order:2]数据创建, 编号:" + planAllocatePubEvent.getSource());
        doSomething();
    }

    public void doSomething(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            LOG.error(e.getLocalizedMessage(), e);
        }
    }
}
复制代码
ノートイベントリスナの実行結果
INFO:2017-09-11 20:57:00.167[publishEvent] [事件发布] 数据创建, 编号:1 
INFO:2017-09-11 20:57:00.168[annoEnvListener1] [注解事件监听][Order:1]数据创建, 编号:1 
INFO:2017-09-11 20:57:03.169[annoEnvListener2] [注解事件监听][Order:2]数据创建, 编号:1 
INFO:2017-09-11 20:57:06.175[publishEvent] [事件发布] 数据创建, 编号:2 
INFO:2017-09-11 20:57:06.176[annoEnvListener1] [注解事件监听][Order:1]数据创建, 编号:2 
INFO:2017-09-11 20:57:09.180[annoEnvListener2] [注解事件监听][Order:2]数据创建, 编号:2 
INFO:2017-09-11 20:57:12.184[publishEvent] [事件发布] 数据创建, 编号:3 
INFO:2017-09-11 20:57:12.185[annoEnvListener1] [注解事件监听][Order:1]数据创建, 编号:3 
INFO:2017-09-11 20:57:15.191[annoEnvListener2] [注解事件监听][Order:2]数据创建, 编号:3 
INFO:2017-09-11 20:57:18.195[publishEvent] [事件发布] 数据创建, 编号:4 
INFO:2017-09-11 20:57:18.196[annoEnvListener1] [注解事件监听][Order:1]数据创建, 编号:4 
INFO:2017-09-11 20:57:21.198[annoEnvListener2] [注解事件监听][Order:2]数据创建, 编号:4 
复制代码

おすすめ

転載: juejin.im/post/5dfb2b6d51882512275313fa