zoukankan      html  css  js  c++  java
  • Spring 事件

    JDK事件

    java通过java.util.EventObject类和java.util.EventListener接口描述事件和监听器

    事件源,事件的产生者,任何一个EventObject都必须拥有一个事件源。
    事件监听器注册表,保存事件监听器的地方。
    事件广播器,把事件通知给事件监听器。
    事件源、事件监听器注册表和事件广播这3个角色有时可以由同一个对象承担,如java.swing包中的JButton、JCheckBox等组件,它们分别集以上3个角色于一身。

    事件体系是观察者模式的一种具体实现方式


    Spring 事件

    Spring的ApplicationContext能够发布事件并且允许注册相应的事件监听器

    Spring事件类ApplicationEvent

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

    Spring事件类ApplicationEvent有两个子类ApplicationContextEvent、RequestHandledEvent

    // 容器事件类
    public abstract class ApplicationContextEvent extends ApplicationEvent {}
    // 与web应用相关的事件RequestHandledEvent,当一个Http请求被处理后,产生该事件
    public class RequestHandledEvent extends ApplicationEvent {}

    ApplicationContextEvent有4个子类ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent,分别表示容器启动、刷新、停止及关闭的事件。

    RequestHandledEvent只有定义了DispatcherServlet时才会产生该事件,它的子类ServletRequestHandledEvent代表Servlet请求事件。


    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





  • 相关阅读:
    各种素材类精品网站
    Java如何设置代理ip
    Spring事务的实现方式和原理以及隔离级别?
    Spring 是什么?
    线程池中阻塞队列的作用?为什么是先添加队列而不是先创建最大线程?
    为什么用线程池?解释下线程池参数
    并发三大特性
    ThreadLocal的原理和使用场景。
    谈谈对线程安全的理解
    sleep,wait,join,yield
  • 原文地址:https://www.cnblogs.com/Mike_Chang/p/10283572.html
Copyright © 2011-2022 走看看