Skip to content

@EventListener事件监听

使用场景举例

用户注册后执行 -> 1.发送注册成功邮件、2.发送优惠券。不管后面的1、2执行是否成功,都应保证用户注册功能不受影响。

使用方式

  1. 创建事件类。其实就是定义一个实体类,里面是业务处理用到的参数
java
/*
 * 自定义的一个实体类,Spring会默认将其包装在PayloadApplicationEvent中
 * 当使用@EventListener时,需指定指定参数value或class,防止多个事件冲突
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserRegisterEvent {
    //用户名
    private String userName;
}
  1. 创建监听类。监听事件进行后续处理,注意使用时需要指定classes事件类,防止冲突
java
**
 * 多个监听器一定指定事件类型,防止发生冲突
 * 如:@EventListener(classes = UserRegisterEvent.class)
 */
@Component
public class UserRegisterListener {
 
    /*
     * 只监听UserRegisterEvent事件
     * 使用Order来表示同一事件的执行顺序,数值越小优先级越高
     */
    @Order(2)
    @EventListener(classes = UserRegisterEvent.class)
    public void sendMail(UserRegisterEvent event) {
        System.out.println(Thread.currentThread().getName() + " ---> " + String.format("给用户【%s】发送注册成功邮件!", event.getUserName()));
    }
 
    @Order(1)
    @EventListener(classes = UserRegisterEvent.class)
    public void sendCompon(UserRegisterEvent event) {
        System.out.println(Thread.currentThread().getName() + " ---> " + String.format("给用户【%s】发送优惠券!", event.getUserName()));
    }
 
    /*
     * 只监听GoodsPriceEvent事件
     * 也就是当触发上面的UserRegisterEvent事件时,不会执行,避免了冲突
     */
    @EventListener(classes = GoodsPriceEvent.class)
    @Order(4)
    public void sendMail2(Object event) {
        System.out.println(Thread.currentThread().getName() + " ---> " + "我也执行了222222222!");
    }
 
}

错误的使用

指定事件类时,不要写Object.class,因为它不是一个明确的事件类,它能监听到所有事件

java
**
 * 多个监听器一定指定事件类型,防止发生冲突
 * 如:@EventListener(classes = UserRegisterEvent.class)
 */
@Component
public class UserRegisterListener {
 
    /*
     * Object类型不要写,所有的事件他都会执行
     */
    @EventListener(classes = Object.class)
    @Order(3)
    public void sendMail1(Object event) {
        System.out.println(Thread.currentThread().getName() + " ---> " + "我也执行了111111111!");
    }
 
}

事件广播

java
/*
 * 这里就是你的Service业务处理类
 * 使用ApplicationEventPublisher发送
 * 当然也可以使用ApplicationContext发送,因为ApplicationContext继承了ApplicationEventPublisher,使用哪个都行
 */
@Service
public class UserRegisterService {
  
    /*
     * 和ApplicationContext任选其一即可
     */
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;
 
    /*
     * 和ApplicationEventPublisher任选其一即可
     */
    @Resource
    private ApplicationContext applicationContext;
 
    /**
     * 负责用户注册及发布事件的功能
     *
     * @param userName 用户名
     */
    public void registerUser(String userName) {
        //用户注册(将用户信息入库等操作)
        System.out.println(String.format("用户【%s】注册成功", userName));
        //发布注册成功事件
        applicationEventPublisher.publishEvent(new UserRegisterEvent(userName));
    }
 
}