Spring 事件

JDK事件java

java經過java.util.EventObject類和java.util.EventListener接口描述事件和監聽器web

事件源,事件的產生者,任何一個EventObject都必須擁有一個事件源。
事件監聽器註冊表,保存事件監聽器的地方。
事件廣播器,把事件通知給事件監聽器。
事件源、事件監聽器註冊表和事件廣播這3個角色有時能夠由同一個對象承擔,如java.swing包中的JButton、JCheckBox等組件,它們分別集以上3個角色於一身。spring

事件體系是觀察者模式的一種具體實現方式app


Spring 事件ide

Spring的ApplicationContext可以發佈事件而且容許註冊相應的事件監聽器post

Spring事件類ApplicationEventthis

// 繼承了JDK的EventObject
public abstract class ApplicationEvent extends EventObject {
    // 惟一的構造方法,source指定事件源
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }
}

Spring事件類ApplicationEvent有兩個子類ApplicationContextEvent、RequestHandledEventspa

// 容器事件類
public abstract class ApplicationContextEvent extends ApplicationEvent {}
// 與web應用相關的事件RequestHandledEvent,當一個Http請求被處理後,產生該事件
public class RequestHandledEvent extends ApplicationEvent {}

ApplicationContextEvent有4個子類ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent,分別表示容器啓動、刷新、中止及關閉的事件。code

RequestHandledEvent只有定義了DispatcherServlet時纔會產生該事件,它的子類ServletRequestHandledEvent表明Servlet請求事件。xml


spring事件監聽器 

// 繼承了JDK的EventListener接口
// E extends ApplicationEvent是一個泛型
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    // 只定義了一個方法
    void onApplicationEvent(E event);
}

ApplicationListener有兩個子類GenericApplicationListener、SmartApplicationListener

public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
    /**
     * 指定監聽器支持哪一種類型的容器事件
     */
    boolean supportsEventType(Class<? extends ApplicationEvent> eventType);

    /**
     * 指定監聽器僅對何種事件源對象作出響應
     */
    boolean supportsSourceType(Class<?> sourceType);

}

public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
    /**
     * 指定監聽器對何種事件類型作出響應
     */
    boolean supportsEventType(ResolvableType eventType);

    /**
     * 指定監聽器對何種事件源作出響應
     */
    boolean supportsSourceType(Class<?> sourceType);

}

spring事件廣播器 

public interface ApplicationEventMulticaster {}

ApplicationEventMulticaster有兩個子類AbstractApplicationEventMulticaster、SimpleApplicationEventMulticaster

public abstract class AbstractApplicationEventMulticaster
        implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {}    
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {}    

AbstractApplicationContext

AbstractApplicationContext有一個成員變量applicationEventMulticaster,這個成員變量提供了容器監聽器的註冊表

AbstractApplicationContext的refresh方法

    postProcessBeanFactory(beanFactory);
    invokeBeanFactoryPostProcessors(beanFactory);
    registerBeanPostProcessors(beanFactory);
    initMessageSource();
    /* 
     * 初始化應用上下文事件廣播器
     * 能夠自定義事件廣播器,實現ApplicationEventMulticaster便可,
     * 若是沒有找到自定義的廣播器,自動使用SimpleApplicationEventMulticaster做爲事件廣播器
     */
    initApplicationEventMulticaster();
    onRefresh();
    /* 
     * 註冊事件監聽器
     * 根據反射機制,從BeanDefinitionRegistry中找出全部實現了ApplicationListener的Bean,
     * 並註冊
     */
    registerListeners();
    finishBeanFactoryInitialization(beanFactory);
    // 容器啓動完成,向容器中的全部監聽器發佈事件
    finishRefresh();

demo

      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.16.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.16.RELEASE</version>
      </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.16.RELEASE</version>
        </dependency>
pom.xml
package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ApplicationContextEvent;

/**
 * 自定義的郵件發送事件類,繼承自ApplicationContextEvent
 */
public class MailSendEvent extends ApplicationContextEvent {
    private String to;
    // 事件源source是ApplicationContext
    public MailSendEvent(ApplicationContext source, String to) {
        super(source);
        this.to = to;
    }
    public String getTo() {
        return this.to;
    }
}
自定義事件類
package test;

import org.springframework.context.ApplicationListener;
/**
 * 自定義的郵件發送事件監聽器,繼承自ApplicationListener
 */
public class MailSendListener implements ApplicationListener<MailSendEvent>{
    // 接收到事件後的處理邏輯
    public void onApplicationEvent(MailSendEvent event) {
            MailSendEvent mse = (MailSendEvent) event;
            System.out.println("MailSendListener:向" + mse.getTo() + "發送完一封郵件");
    }
}
自定義事件監聽器
package test;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class MailSender implements ApplicationContextAware {
    private ApplicationContext ctx ;
    // 實現了ApplicationContextAware,在bean的生命週期會自動調用這個方法
    public void setApplicationContext(ApplicationContext ctx)
            throws BeansException {
        this.ctx = ctx;

    }    
    public void sendMail(String to){
        // 發送郵件
        System.out.println("MailSender:模擬發送郵件...");
        // 建立事件
        MailSendEvent mse = new MailSendEvent(this.ctx,to);
        // 發佈事件
        ctx.publishEvent(mse);
    }
}
郵件發送器
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:p="http://www.springframework.org/schema/p"
       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 id="sender" class="test.MailSender"/>
    <bean id="sendListener" class="test.MailSendListener"/>
</beans>
my.xml
package test;

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

public class Driver {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("my.xml");
        MailSender mailSender = ctx.getBean(MailSender.class);
        mailSender.sendMail("test mail.");
        System.out.println("done.");
    }
}
Driver
相關文章
相關標籤/搜索