第1章 Spring 订阅与发布


Spring 的订阅与发布事件功能是非常有用的。要使用Spring的订阅与发布事件功能,需要以下步骤:

  • 在Spring 4.2版本之前,自定义的 Event 需要继承 ApplicationEvent ;在Spring 4.2版本开始,自定义的 Event 不再需要继承 ApplicationEvent
  • 事件发布者需要注入 ApplicationEventPublisher
  • 事件监听者需要实现 ApplicationListener 接口
发布与监听事件
自定义事件
public class MyEvent extends ApplicationEvent {
    private String message;

    public MyEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}
定义事件发布者
@Component
public class MyPublisher {
    @Autowired
    private ApplicationEventPublisher publisher;
    
    public void publishEvent(String message) {
        publisher.publishEvent(new MyEvent(this, message));
    }
}

从Spring 4.2开始,ApplicationEventPublisher 接口提供一个方法 publishEvent(Object Event) ,参数是Object对象。这就意味着 Spring的事件不再需要扩展 Application 类。

定义监听者
@Component
public class MyListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        System.out.println("处理事件: " + event.getMessage());
    }
}
单元测试
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
class MyPublisherTest {

    @Autowired
    private MyPublisher publisher;

    @Test
    void publishEvent() {
        publisher.publishEvent("Spring 的监听事件");
    }
}
异步执行

spring boot 的事件监听默认是同步执行的。这就意味着发布者的线程将会阻塞,直到监听器执行完成。如果开启事件监听器异步执行,我们创建 ApplicationEventMulticaster 对象,并给它添加一个 executor,最后注册到容器中。

@Configuration
public class AsynchronousSpringEventsConfig {
    @Bean(name = "applicationEventMulticaster")
    public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
        SimpleApplicationEventMulticaster eventMulticaster =
          new SimpleApplicationEventMulticaster();
        
        eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return eventMulticaster;
    }
}
使用注解监听事件

从Spring4.2开始,事件监听器不再需要实现 ApplicationListener 接口,只需要添加注解 @EventListenerpublic 方法上即可。

@Component
public class MySecondListener {

    @EventListener
    public void handlerEvent(MyEvent event) {
        System.out.println("使用注解处理事件:" + event.getMessage());
    }
}

@EventListener 有个 condition 属性,我们可以用来指定过滤特定的事件。当 condition 属性执行结果为true时,事件监听才会执行。condition 使用EL表达式。

@Component
public class MySecondListener {

    @EventListener(condition = "#myEvent.message.length() > 1")
    public void handlerEvent(MyEvent myEvent) {
        System.out.println("使用注解处理事件:" + myEvent.getMessage() );
    }
}

当事件 MyEvent 的message属性的长度大于1时,执行。

使用注解开启异步

Spring 的异步监听器可以通过注解 @Async 来开启异步执行。除了增加 注解 @Async 以外,我们还需要在 @Configuration 的配置类或 @SpringBootApplication 的类上加上注解 @EnableAsync,用来激活 @Async 注解。

@Component
public class MySecondListener {

    @Async
    @EventListener
    public void handlerEvent(MySecondEvent myEvent) {
        System.out.println("使用注解处理事件:" + myEvent.getMessage() );
    }
}

想要了解更多关于 @EventListener 的信息可以参考一下:

泛型的事件监听

Spring支持带有泛型的事件,这样可以更加灵活发布任意对象的事件。

定义带有泛型的事件
public class GenericEvent<T> implements ResolvableTypeProvider{

    private T msg;
    private boolean success;

    public GenericEvent(T msg, boolean success) {
        this.msg = msg;
        this.success = success;
    }

    @Override
    public ResolvableType getResolvableType() {
        return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(msg));
    }

    // getter and setter
}
事件监听器
@Component
public class GenericEventListener {

    @EventListener(condition = "#event.success")
    public void handlerGenericEvent(GenericEvent<String> event) {
        System.out.println("处理带有泛型的事件: " + event.getMsg());
    }
}
事务事件监听器

从Spring4.2开始,提供一个新的注解 @TransactionalEventListener ,这个注解是用来监听事务的状态。这里事务的状态4个:

  • AFTER_COMMIT:如果事务已经成功完成,将会触发该事件。
  • AFTER_ROLLBACK:如果事务回滚,将会触发该事件。
  • AFTER_COMPLETION:如果事务完成,将会触发该事件(包括 AFTER_COMMIT 和 AFTER_ROLLBACK)
参考
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值