1. 程式人生 > >Spring事件機制

Spring事件機制

Java提供了事件機制,在使用spring的時候,我們可以把普通的java事件操作定義為bean整合到bean容器中,但還有一種更方便的方式,即使用spring已整合的事件支援。
在使用Spring的事件支援時,我們需要關注以下幾個物件:
      1. ApplicationEvent:繼承自EventObject,同時是spring的application中事件的父類,需要被自定義的事件繼承。
      2. ApplicationListener:繼承自EventListener,spring的application中的監聽器必須實現的介面,需要被自定義的監聽器實現其onApplicationEvent方法
      3. ApplicationEventPublisherAware:在spring的context中希望能釋出事件的類必須實現的介面,該介面中定義了設定ApplicationEventPublisher的方法,由ApplicationContext呼叫並設定。在自己實現的ApplicationEventPublisherAware子類中,需要有ApplicationEventPublisher屬性的定義。
      4. ApplicationEventPublisher:spring的事件釋出者介面,定義了釋出事件的介面方法publishEvent。因為ApplicationContext實現了該介面,因此spring的ApplicationContext例項具有釋出事件的功能(publishEvent方法在AbstractApplicationContext中有實現)。在使用的時候,只需要把ApplicationEventPublisher的引用定義到ApplicationEventPublisherAware的實現中,spring容器會完成對ApplicationEventPublisher的注入。

在spring的bean配置中,因為事件是由事件源發出的,不需要註冊為bean由spring容器管理。所以在spring的配置中,只需配置自定義的ApplicationEventListener和publisherAware(即實現了ApplicationEventPublisherAware介面的釋出類),而對於ApplicationEventPublisher的管理和注入都由容器來完成。

基於spring的事件簡單實現如下:
1. 定義ApplicationEvent
Java程式碼
複製程式碼
 收藏程式碼
  1. package com.nuc.event;   
  2. import org.springframework.context.ApplicationEvent;   
  3. /**  
  4.  * 定義Spring容器中的事件,與java普通的事件定義相比,只是繼承的父類不同而已,在  
  5.  * 在定義上並未有太大的區別,畢竟ApplicationEvent也是繼承自EventObject的。  
  6.  */  
  7. public class MethodExecutionEvent extends ApplicationEvent {   
  8.     private static final long serialVersionUID = 2565706247851725694L;   
  9.     private String methodName;   
  10.     private MethodExecutionStatus methodExecutionStatus;   
  11.     public MethodExecutionEvent(Object source) {   
  12.         super(source);   
  13.     }   
  14.     public MethodExecutionEvent(Object source, String methodName, MethodExecutionStatus methodExecutionStatus) {   
  15.         super
    (source);   
  16.         this.methodName = methodName;   
  17.         this.methodExecutionStatus = methodExecutionStatus;   
  18.     }   
  19.     public String getMethodName() {   
  20.         return methodName;   
  21.     }   
  22.     public void setMethodName(String methodName) {   
  23.         this.methodName = methodName;   
  24.     }   
  25.     public MethodExecutionStatus getMethodExecutionStatus() {   
  26.         return methodExecutionStatus;   
  27.     }   
  28.     public void setMethodExecutionStatus(MethodExecutionStatus methodExecutionStatus) {   
  29.         this.methodExecutionStatus = methodExecutionStatus;   
  30.     }   
  31. }  
package com.nuc.event;

import org.springframework.context.ApplicationEvent;
/**
 * 定義Spring容器中的事件,與java普通的事件定義相比,只是繼承的父類不同而已,在
 * 在定義上並未有太大的區別,畢竟ApplicationEvent也是繼承自EventObject的。
 */
public class MethodExecutionEvent extends ApplicationEvent {

    private static final long serialVersionUID = 2565706247851725694L;
    private String methodName;
    private MethodExecutionStatus methodExecutionStatus;
    
    public MethodExecutionEvent(Object source) {
        super(source);
    }
    
    public MethodExecutionEvent(Object source, String methodName, MethodExecutionStatus methodExecutionStatus) {
        super(source);
        this.methodName = methodName;
        this.methodExecutionStatus = methodExecutionStatus;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public MethodExecutionStatus getMethodExecutionStatus() {
        return methodExecutionStatus;
    }

    public void setMethodExecutionStatus(MethodExecutionStatus methodExecutionStatus) {
        this.methodExecutionStatus = methodExecutionStatus;
    }
}

2. 定義ApplicationEventListener
Java程式碼 複製程式碼 收藏程式碼
  1. package com.nuc.listener;   
  2. import org.springframework.context.ApplicationEvent;   
  3. import org.springframework.context.ApplicationListener;   
  4. import com.nuc.event.MethodExecutionEvent;   
  5. import com.nuc.event.MethodExecutionStatus;   
  6. /**  
  7.  * Spring容器中的事件監聽器,與java中基本的事件監聽器的定義相比,這裡需要實現ApplicationListener介面  
  8.  * ApplicationListener介面雖然繼承自EventListener,但擴充套件了EventListener  
  9.  * 它在介面宣告中定義了onApplicationEvent的介面方法,而不像EventListener只作為標記性介面。  
  10.  */  
  11. public class MethodExecutionEventListener implements ApplicationListener {   
  12.     public void onApplicationEvent(ApplicationEvent event) {   
  13.         if (event instanceof MethodExecutionEvent) {   
  14.            if (MethodExecutionStatus.BEGIN   
  15.                     .equals(((MethodExecutionEvent) event)   
  16.                             .getMethodExecutionStatus())) {   
  17.                 System.out.println("It's beginning");   
  18.             }   
  19.             if (MethodExecutionStatus.END.equals(((MethodExecutionEvent) event).getMethodExecutionStatus())) {   
  20.                 System.out.println("It's ending");   
  21.             }   
  22.         }   
  23.     }   
  24. }  
package com.nuc.listener;

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

import com.nuc.event.MethodExecutionEvent;
import com.nuc.event.MethodExecutionStatus;
/**
 * Spring容器中的事件監聽器,與java中基本的事件監聽器的定義相比,這裡需要實現ApplicationListener介面
 * ApplicationListener介面雖然繼承自EventListener,但擴充套件了EventListener
 * 它在介面宣告中定義了onApplicationEvent的介面方法,而不像EventListener只作為標記性介面。
 */

public class MethodExecutionEventListener implements ApplicationListener {

    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof MethodExecutionEvent) {
           if (MethodExecutionStatus.BEGIN
                    .equals(((MethodExecutionEvent) event)
                            .getMethodExecutionStatus())) {
                System.out.println("It's beginning");
            }
            if (MethodExecutionStatus.END.equals(((MethodExecutionEvent) event).getMethodExecutionStatus())) {
                System.out.println("It's ending");
            }
        }
    }
}

3. 定義ApplicationEventPublisherAware
Java程式碼 複製程式碼 收藏程式碼
  1. package com.nuc.publisher;   
  2. import org.springframework.context.ApplicationEventPublisher;   
  3. import org.springframework.context.ApplicationEventPublisherAware;   
  4. import com.nuc.event.MethodExecutionEvent;   
  5. import com.nuc.event.MethodExecutionStatus;   
  6. public class MethodExecutionEventPublisher implements  
  7.         ApplicationEventPublisherAware {   
  8.     private ApplicationEventPublisher eventPublisher;   
  9.     public void methodToMonitor() {   
  10.         MethodExecutionEvent beginEvent = new MethodExecutionEvent(this"methodToMonitor", MethodExecutionStatus.BEGIN);   
  11.         this.eventPublisher.publishEvent(beginEvent);   
  12.         //TODO   
  13.         MethodExecutionEvent endEvent = new MethodExecutionEvent(this"methodToMonitor", MethodExecutionStatus.END);   
  14.         this.eventPublisher.publishEvent(endEvent);   
  15.     }   
  16.     public void setApplicationEventPublisher(   
  17.             ApplicationEventPublisher applicationEventPublisher) {   
  18.         this.eventPublisher = applicationEventPublisher;   
  19.     }   
  20. }  
package com.nuc.publisher;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

import com.nuc.event.MethodExecutionEvent;
import com.nuc.event.MethodExecutionStatus;

public class MethodExecutionEventPublisher implements
        ApplicationEventPublisherAware {

    private ApplicationEventPublisher eventPublisher;
    
    public void methodToMonitor() {
        MethodExecutionEvent beginEvent = new MethodExecutionEvent(this, "methodToMonitor", MethodExecutionStatus.BEGIN);
        this.eventPublisher.publishEvent(beginEvent);
        //TODO
        MethodExecutionEvent endEvent = new MethodExecutionEvent(this, "methodToMonitor", MethodExecutionStatus.END);
        this.eventPublisher.publishEvent(endEvent);
    }
    
    public void setApplicationEventPublisher(
            ApplicationEventPublisher applicationEventPublisher) {
        this.eventPublisher = applicationEventPublisher;
    }
}

4. 定義bean配置
Java程式碼 複製程式碼 收藏程式碼
  1. <?xml version="1.0" encoding="GBK"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"  
  5.     default-autowire="byName">   
  6.     <bean id="methodExecListener" class="com.nuc.listener.MethodExecutionEventListener"></bean>   
  7.     <bean id="evtPublisher" class="com.nuc.publisher.MethodExecutionEventPublisher"></bean>    
  8. </beans>  
<?xml version="1.0" encoding="GBK"?>
<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-2.0.xsd"
	default-autowire="byName">
	<bean id="methodExecListener" class="com.nuc.listener.MethodExecutionEventListener"></bean>
	<bean id="evtPublisher" class="com.nuc.publisher.MethodExecutionEventPublisher"></bean>	
</beans>

5. 使用事件
Java程式碼 複製程式碼 收藏程式碼
  1. package com.nuc;   
  2. import org.springframework.context.ApplicationContext;   
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  4. import com.nuc.publisher.MethodExecutionEventPublisher;   
  5. public class App    
  6. {   
  7.     public static void main( String[] args )   
  8.     {   
  9.         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");   
  10.         MethodExecutionEventPublisher publisher = (MethodExecutionEventPublisher)context.getBean("evtPublisher");   
  11.         publisher.methodToMonitor();   
  12.     }   
  13. }  
package com.nuc;

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

import com.nuc.publisher.MethodExecutionEventPublisher;

public class App 
{
    public static void main( String[] args )
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        MethodExecutionEventPublisher publisher = (MethodExecutionEventPublisher)context.getBean("evtPublisher");
        publisher.methodToMonitor();
    }
}


從實現來上,和使用基本的java事件流程大體一致,不同的是這裡不需要自定義釋出者,而使用spring實現提供的事件釋出實現。當然,這裡卻引入了ApplicationEventPublisherAware。