1. 程式人生 > >Spring 原始碼解析 ---- 事件監聽

Spring 原始碼解析 ---- 事件監聽

一. 測試用例

package main.java.com.wenniuwuren.spring.event.listener;


import org.springframework.context.ApplicationEvent;

/**
 * 定義監聽事件
 * Created by hzzhuyibin on 2016/11/22.
 */
public class TestEvent extends ApplicationEvent {

public String msg;

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

public TestEvent(Object source, String msg) {
super(source);
 this.msg = msg;
 }

public void print() {
System.out.println(msg);
 }

}

package main.java.com.wenniuwuren.spring.event.listener;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

/**
 * 定義監聽器
 * Created by hzzhuyibin on 2016/11/22.
 */
public class TestListener implements ApplicationListener{
@Override
 public void onApplicationEvent(ApplicationEvent event) {

if (event instanceof TestEvent) {
TestEvent testEvent = (TestEvent)event;
 testEvent.print();
 }
}
}

listenerTest.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="testListener" class="main.java.com.wenniuwuren.spring.event.listener.TestListener"/>

</beans>

測試類:
package main.java.com.wenniuwuren.spring.event.listener;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 *
 * Created by Yibin_Zhu on 2016/11/21.
 */
public class Test{

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("main/resources/listenerTest.xml");
        // 不僅僅可以指定 beanName,也可以有建構函式或者工廠方法的方法引數

        TestEvent testEvent = new TestEvent("hello", "wenniuwuren");

        context.publishEvent(testEvent);

    }
}


二. 原始碼解析 debug 到 AbstractApplicationContext 類的 initApplicationEventMulticaster() 方法 廣播器我們又經常成為事件
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.isDebugEnabled()) {
         logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
   }
   else { // 預設事件廣播器
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isDebugEnabled()) {
         logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
               APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
               "': using default [" + this.applicationEventMulticaster + "]");
      }
   }
}

我們關注的是 SimpleApplicationEventMulticaster 事件類的具體實現,繼續 debug 進去,看到此類繼承自 AbstractApplicationEventMulticaster, 而 AbstractApplicationEventMulticaster 中有許多 add**Listener、delete**Listener 之類的方法,可以知道這是典型的觀察者模式的應用。 繼續看如下方法:事件在這裡廣播,遍歷所有監聽器,通知監聽器
@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);
      }
   }
}

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

這個方法 debug 結束,回到 AbstractApplicationContext 類,debug 進 registerListeners() 方法:註冊監聽器
protected void registerListeners() {
   // 硬編碼的方式註冊監聽器
   for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

   // 配置檔案註冊監聽器
   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);
      }
   }
}


相關推薦

Spring 原始碼解析 ---- 事件

一. 測試用例 package main.java.com.wenniuwuren.spring.event.listener; import org.springframework.context.ApplicationEvent; /** * 定義監聽事件 *

Spring Boot實踐——事件

width tar java nco csdn ONBUILD man 初始 ebo 借鑒:https://blog.csdn.net/Harry_ZH_Wang/article/details/79691994    https://blog.csdn.net/igno

Spring中的事件機制在專案中的應用

最經在做專案的時候,呼叫某個介面的時候為了呼叫地圖,而不希望因為呼叫超時影響到主執行緒,使用了spring的時間監聽機制。 Spring中提供一些Aware相關的介面,BeanFactoryAware、 ApplicationContextAware、Reso

spring事件機制

ide could 事情 task object 負責 his try and 事件機制的主要成員:   事件 事件監聽器(監聽事件觸發,處理一些事情) 事件源(發布事件) javaSE 提供了一系列自定義事件的標準。 EvenObject,為javaSE提供

spring boot 專案重新搭建----------定時任務、事件

1.開啟定時任務 . [email protected]設定定時時間規則 3.有時候需要程式啟動就進行執行的操作可用事件監聽來實現 監聽ContextRefreshedEvent事件,當所有的bean都初始化完成並被成功裝載後會觸發該事件,實現Applicati

Spring事件及應用

最近公司在重構廣告系統,其中核心的打包功由廣告系統呼叫,即對apk打包的呼叫和打包完成之後的回撥,需要提供相應的介面給廣告系統。因此,為了將apk打包的核心流程和對接廣告系統的業務解耦,利用了spring的事件監聽特性來滿足需求。以下說明spring的事件機制的相關內容。   1.觀察

深入理解Spring事件機制

目錄 1. 什麼是事件監聽機制 在講解事件監聽機制前,我們先回顧下設計模式中的觀察者模式,因為事件監聽機制可以說是在典型觀察者模式基礎上的進一步抽象和改進。我們可以在JDK或者各種開源框架比如Spring中看到它的身影,從這個意義上說,事件監聽機制也可以看做一種對傳統觀察者模式的具體實現,不同的框架對其實現

Spring中的觀察者模式-事件

      在編碼過程中,我們經常會遇到完成一個操作需要多個步驟完成的情況。我們可能會把多個步驟寫到一個方法裡,假如這個操作需要新增步驟,那麼勢必要修改已有的方法,這違反了開閉原則。      我們可以使用spring的事件機制來簡單地實現這種功能

java事件機制,spring中的event listener模式和解耦

event,listener是observer模式一種體現,在spring 3.0.5中,已經可以使用annotation實現event和eventListner裡。我們以spring-webflow裡的hotel booking為例,看一下實現,步驟如下:1,建立eve

Android 解析RecyclerView(1)——帶點選事件的通用Adapter

按照最原始的做法,構建一個RecyclerView Adapter需要寫挺多程式碼的,而通過對Java泛型的使用,可以使程式碼量變得只需十幾行即可。此外,由於RecyclerView不像ListView那樣支援直接新增頂部View,也不支援直接新增點選事件監

spring 事件 3種方式

http://blog.csdn.net/fhx007/article/details/5416376http://blog.csdn.net/it_man/article/details/8440737http://javabeat.net/spring-eventlist

spring的自定義事件

前言: 今天寫程式碼的時候遇到了監聽器,然後我就鬼使神差的翻了一下Spring框架文件,看到了自定義監聽事件,下面是我的收穫分享。 標準事件 spring中自帶有5種標準事件,ContextRefreshedEvent,ContextStartedEv

Spring事件模式應用場景和思路

什麼是事件  程式中的事件其實和現實差不多,例如:Js中的事件有很多 如滑鼠的單擊事件onclick。 當點選某個按鈕時--觸發某個方法。當你不去觸發這個事件、這個事件就永遠的在等待 喚醒事件的人; 事件三要素 1、定義一個事件(火災事件、碰撞事件、收到資訊事件。。。

spring boot事件

事件監聽示例    1,自定義事件,一般是繼承ApplicationEvent抽象類        2,定義事件監聽器,一般是實現ApplicationListener介面         3,配置監聽器,釋出事件        4,配置監聽器的方法        (1),如

Spring ApplicationContext(八)事件機制

一個 ace end oid 其它 get throws 規範 bstr Spring ApplicationContext(八)事件監聽機制 本節則重點關註的是 Spring 的事件監聽機制,主要是第 8 步:多播器註冊;第 10 步:事件註冊。 public void

Spring事件(觀察者模型)

respond reg nal @override ace sin 繼承 abstract http 目錄 Spring事件監聽 一、事件監聽案例 1.事件類 2.事件監聽

SpringBoot事件機制原始碼分析(上) SpringBoot原始碼(九)

SpringBoot中文註釋專案Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplication物件是如何構建的? SpringBoot原始碼(八) 1 溫故而知新 溫故而知新,我們來簡單回顧一下上篇

Spring 事件機制及原理分析

## 簡介 在JAVA體系中,有支援實現事件監聽機制,在Spring 中也專門提供了一套事件機制的介面,方便我們實現。比如我們可以實現當用戶註冊後,給他傳送一封郵件告訴他註冊成功的一些資訊,比如使用者訂閱的主題更新了,通知使用者注意及時檢視等。 ## 觀察者模式 觀察者模式還有很多其他的稱謂,如釋出-訂

JS 事件綁定、事件事件委托詳細介紹

兼容性 log 查看 and == 常用 提高 監聽 live 事件綁定 要想讓 JavaScript 對用戶的操作作出響應,首先要對 DOM 元素綁定事件處理函數。所謂事件處理函數,就是處理用戶操作的函數,不同的操作對應不同的名稱。 在JavaScript中,有三種常用的

JS中的事件事件

pan 交互 ack 其他 獲得 發生 listen 監聽器 pre 事件監聽:   使用監聽器(eventListener)來預定事件,在傳統軟件工程中稱成為觀察者模式   執行某種操作時(特定的交互瞬間),會產生對象,對象會沿事件流的方向傳播。 事件流:   事件流有