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

  • 相关阅读:
    ExecuteScalar requires the command to have a transaction when the connection assigned to the command is in a pending
    如何从vss中分离程序
    String or binary data would be truncated
    the pop3 service failed to retrieve authentication type and cannot continue
    The POP3 service failed to start because
    IIS Error he system cannot find the file specified _找不到页面
    pku2575Jolly Jumpers
    pku2940Wine Trading in Gergovia
    pku3219二项式系数
    pku1029false coin
  • 原文地址:https://www.cnblogs.com/MattCheng/p/9046980.html
Copyright © 2011-2022 走看看