• Spring 使用介绍(十一)—— Spring事件


    一、简介

    spring事件是观察者设计模式的实现,主要有三个元素:

    • 事件  spring事件由ApplicationEvent定义
    • 监听者  由ApplicationListener定义
    • 发布者  由ApplicationEventPublisher定义,而ApplicationContext继承自ApplicationEventPublisher

    简单示例:

    自定义事件

    public class TestEvent extends ApplicationEvent {
        
        private String message;
    
        public TestEvent(Object source) {
            this(source, "default message");
        }
        
        public TestEvent(Object source, String msg) {
            super(source);
            this.message = msg;
        }
    
        public String getMessage() {
            return message;
        }
    }

    监听者

    @Component
    public class TestListener implements ApplicationListener<ApplicationEvent>  {
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if (event instanceof TestEvent) {
            System.out.println(((TestEvent)event).getMessage());
            }    
        }
    }

    XML配置

    <context:component-scan base-package="cn.matt.event"/>  

    测试

    public class EventTest {
        @Test
        public void testCustomEvent() {
            ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-context.xml");
            context.publishEvent(new TestEvent("", "hello matt"));
        }
    }

    补充:

    定义监听者时,可通过泛型指定监听事件类型,因此,上例监听者可定义如下:

    @Component
    public class TestListener implements ApplicationListener<TestEvent> {
        @Override
        public void onApplicationEvent(TestEvent event) {
            System.out.println(((TestEvent) event).getMessage());
        }
    }

    二、spring容器事件

    spring为容器启动各阶段定义了相关事件,实现如图:

    事件说明:

    • ContextStartedEvent:ApplicationContext启动后触发的事件(调用start方法)
    • ContextStoppedEvent:ApplicationContext停止后触发的事件(调用stop方法)
    • ContextClosedEvent:ApplicationContext关闭后触发的事件
    • ContextRefreshedEvent:ApplicationContext初始化或刷新完成后触发的事件(容器初始化(如bean的实例化、依赖注入)完成后调用)

    使用示例

    @Component
    public class ApplicationStartUpListener implements ApplicationListener<ContextRefreshedEvent> {
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {    
            System.out.println("spring context inited");    
        }
    }

    三、事件的执行机制

    spring事件的执行机制默认使用单线程同步执行,异步执行可使用@Async注解实现,示例如下(新用户注册):

    定义事件

    public class RegisterEvent extends ApplicationEvent {
        public RegisterEvent(User user) {
            super(user);
        }
    }

    定义监听者

    // 发生邮件
    @Component
    public class EmailRegisterListener implements ApplicationListener<RegisterEvent> { @Async public void onApplicationEvent(final RegisterEvent event) { System.out.println(Thread.currentThread().getId() + " **** 注册成功,发送确认邮件给:" + ((User)event.getSource()).getUsername()); } }
    // 赠送积分
    @Component
    public class PointRegisterListener implements ApplicationListener<RegisterEvent> {
        @Async
        public void onApplicationEvent(final RegisterEvent event) {
            System.out.println(Thread.currentThread().getId() + " **** 注册成功,赠送积分给:" + ((User)event.getSource()).getUsername());
        }
    }
    // 赠送大礼包
    @Component
    public class PresentRegisterListener implements ApplicationListener<RegisterEvent> {
        @Async
        public void onApplicationEvent(final RegisterEvent event) {
            System.out.println(Thread.currentThread().getId() + " **** 注册成功,赠送大礼包给:" + ((User)event.getSource()).getUsername());
        }
    }

    用户类与业务类

    public class User implements Serializable {
        private String username;
        private String password;
    
        public User(String username, String password) {
            this.username = username;
            this.password = password;
        }
    
        public String getUsername() {
            return username;
        }
    }
    @Service
    public class RegisterService {
        @Autowired
        private ApplicationContext applicationContext;
    
        public void register(String username, String password) {
            System.out.println(username + "注册成功!");
            publishRegisterEvent(new User(username, password));
        }
    
        private void publishRegisterEvent(User user) {
            applicationContext.publishEvent(new RegisterEvent(user));
        }
    }

    配置

    <context:component-scan base-package="com.sishuok"/>
    
    <!-- 任务调度器 -->
    <task:scheduler id="scheduler" pool-size="10"/>
    
    <!-- 任务执行器 -->
    <task:executor id="executor" pool-size="10"/>
    
    <!--开启注解调度支持 @Async @Scheduled-->
    <task:annotation-driven executor="executor" scheduler="scheduler" proxy-target-class="true"/>

    测试

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"classpath:spring-config-register.xml"})
    public class RegisterServiceIT {
        @Autowired
        private RegisterService registerService;
    
        @Test
        public void testRegister() {
             registerService.register("long", "123");
        }
    }
    
    // 输出:
    // long注册成功!
    // 15 **** 注册成功,发送确认邮件给:long
    // 17 **** 注册成功,赠送积分给:long
    // 18 **** 注册成功,赠送大礼包给:long

    参考:

    事件驱动模型简介

    Spring进阶之路(2)-ApplicationContext容器以及事件机制

     Spring ApplicationContext事件机制

  • 相关阅读:
    Hadoop_33_Hadoop HA的搭建
    Hadoop_32_HDFS高可用机制
    Hadoop_31_MapReduce参数优化
    Hadoop_30_MapReduce_多job串联
    Hadoop_29_MapReduce_计数器应用
    Hadoop_28_MapReduce_自定义 inputFormat
    Hadoop_27_MapReduce_运营商原始日志增强(自定义OutputFormat)
    Hadoop_26_MapReduce_Reduce端使用GroupingComparator求同一订单中最大金额的订单
    Hadoop_25_MapReduce实现日志清洗程序
    干货 | 剑指offer系列文章汇总
  • 原文地址:https://www.cnblogs.com/MattCheng/p/9046980.html
Copyright © 2020-2023  润新知