zoukankan      html  css  js  c++  java
  • 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事件机制

  • 相关阅读:
    2018年2月1日学习总结
    2018年1月31日学习总结
    创建oracle数据库表空间和用户
    广播权限声明
    广播接收器
    Android的屏幕限定符
    hibernate学习笔记(3)hibernate常用配置以及session对象
    hibernate学习笔记(2)持久化类测试
    hibernate学习笔记(1)基础配置与jar包
    struts2学习笔记(5)拦截器
  • 原文地址:https://www.cnblogs.com/MattCheng/p/9046980.html
Copyright © 2011-2022 走看看