Spring事件入门

准备三个部分

事件类:定义事件,继承ApplicationEvent的类成为一个事件类。
发布者:发布事件,通过ApplicationEventPublisher发布事件。
监听者:监听并处理事件,实现ApplicationListener接口或者使用@EventListener注解。

事件类

只要继承org.springframework.context.ApplicationEvent,便是一个Spring Event类。
一般我们会专门为一个类型的Event写一个抽象的事件类,作为该类型的所有事件的父类

方法一:定义一个抽象的事件类的父类

/**
 * 账户相关的事件
 */
public abstract class AccountEvent extends ApplicationEvent {

    /**
     * 该类型事件携带的信息
     */
    private AccountEventData eventData;

    /**
     *
     * @param source 最初触发该事件的对象
     * @param eventData 该类型事件携带的信息
     */
    public AccountEvent(Object source, AccountEventData eventData) {
        super(source);
        this.eventData = eventData;
    }

    public AccountEventData getEventData() {
        return eventData;
    }
}
/**
* 推荐使用类实现的方式来发布具体的事件,
* 而不是在事件中使用private String eventType定义事件的类型,
* 监听器只要监听具体的事件类即可,而无需再做判断,同时也不需要再另外维护事件类型列表。
*/
public class AccountCreatedEvent extends AccountEvent {
    public AccountCreatedEvent(Object source, AccountEventData eventData) {
        super(source, eventData);
    }
}

方法二:泛型定义一个统一的父类

public abstract class BaseEvent<T> extends ApplicationEvent {

    /**
     * 该类型事件携带的信息
     */
    private T eventData;

    /**
     *
     * @param source 最初触发该事件的对象
     * @param eventData 该类型事件携带的信息
     */
    public BaseEvent(Object source, T eventData) {
        super(source);
        this.eventData = eventData;
    }

    public T getEventData() {
        return eventData;
    }
}


public class AccountCreatedEvent extends BaseEvent<AccountEventData> {
    public AccountCreatedEvent(Object source, AccountEventData eventData) {
        super(source, eventData);
    }
}

public class TodoCreatedEvent extends BaseEvent<TodoEventData> {
    public TodoCreatedEvent(Object source, TodoEventData eventData) {
        super(source, eventData);
    }
}

发布事件

发布者负责发布消息,有三种实现方式。
Spring容器中默认的ApplicationEventPublisher是AbstractApplicationContext,同时AbstractApplicationContext也是ApplicationContext的一个子类,也就是说,Spring默认使用AbstractApplicationContext发布事件。

方式1:直接使用ApplicationEventPublisher(推荐)

import org.springframework.context.ApplicationEventPublisher;

public class AccountsController {
    
    @Autowired
    private ApplicationEventPublisher publisher;
    
    @PostMapping("")
    public Account createAccount(@RequestBody Account account) {
        
        ...

        publisher.publishEvent(new AccountCreatedEvent(this, new AccountEventData()));
        return account;
    }
}

方式2:实现ApplicationEventPublisherAware接口(推荐)

public interface ApplicationEventPublisherAware extends Aware {

    void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);
}
package org.springframework.data.rest.webmvc;

@RepositoryRestController
class RepositoryEntityController extends AbstractRepositoryRestController implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;
    
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    private ResponseEntity<ResourceSupport> saveAndReturn(Object domainObject, RepositoryInvoker invoker,
                HttpMethod httpMethod, PersistentEntityResourceAssembler assembler, boolean returnBody) {

        publisher.publishEvent(new BeforeSaveEvent(domainObject));
        Object obj = invoker.invokeSave(domainObject);
        publisher.publishEvent(new AfterSaveEvent(obj));

        ...
    }
    ...
}

监听事件

方法一:实现ApplicationListener接口或

方法二:使用@EventListener注解(推荐)

可以使用@EventListener在同一个类中用不同的方法监听多个不同的事件。相对于实现ApplicationListener接口,使用@EventListener会更加灵活。

@Slf4j
@Component
public class SyncAccountListener {

    /**
     * 异步发送邮件
     * @param event
     */
    @EventListener
    public void doOnNormalEvent(NormalAccountEvent event) {
        try {
            log.debug("befor");
            Thread.sleep(1000);
            log.debug("after");
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        }
    }
}
@EventListener(value = {AccountCreatedEvent.class, AccountUpdatedEvent.class}, condition = "#event.account.age > 10")
public void doSomethingOnAccountEvent(AccountEvent event) {
    // TODO
}
value: 监听的事件(组),用于支持同一父类的事件
class: 同value
condition: SpEL,使得Event Handler变得conditional

#root.event, Application的引用
#root.args, 表示方法参数,#root.args[0]表示第0个方法参数
#<name>, 如上面代码中的#event表示以参数名关联参数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值