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事件机制

  • 相关阅读:
    jquery 实现 html5 placeholder 兼容password密码框
    php返回json的结果
    使用PHP读取远程文件
    Sharepoint 自定义字段
    Sharepoint 中新增 aspx页面,并在页面中新增web part
    【转】Sharepoint 2010 配置我的站点及BLOG
    JS 实现 Div 向上浮动
    UserProfile同步配置
    【转】Import User Profile Photos from Active Directory into SharePoint 2010
    Sharepoint 2010 SP1升级后 FIMSynchronizationService 服务无法开启
  • 原文地址:https://www.cnblogs.com/MattCheng/p/9046980.html
Copyright © 2011-2022 走看看