通过继承ApplicationEvent,实现自定义事件。是对 Java EventObject 的扩展,表示 Spring 的事件,Spring 中的所有事件都要基于其进行扩展。其源码如下。我们可以获取到timestamp属性指的是发生时间。
事件发布
/** * @Description 修改密码事件 * @ClassName UserChangePasswordEvent **/ @Getter @Setter public class UserChangePasswordEvent extends ApplicationEvent { private String userId; public UserChangePasswordEvent(String userId) { super(new Object()); this.userId = userId; } }如何监听事件
/** * 堆代码 duidaima.com * @Description 发送短信监听器 * @ClassName MessageListener **/ @Component public class MessageListener implements ApplicationListener<UserChangePasswordEvent> { @Override public void onApplicationEvent(UserChangePasswordEvent event) { System.out.println("收到事件:" + event); System.out.println("开始执行业务操作给用户发送短信。用户userId为:" + event.getUserId()); } }2、 使用@EventListener注解标注处理事件的方法,此时Spring将创建一个ApplicationListenerbean对象,使用给定的方法处理事件源码如下参数可以给指定的事件这里巧妙的用到了@AliasFor的能力,放到了@EventListener身上注意:一般建议都需要指定此值,否则默认可以处理所有类型的事件,范围太广了;
/** * @Description 事件监听器 * @ClassName LogListener **/ @Component public class ListenerEvent { @EventListener({ UserChangePasswordEvent.class }) public void LogListener(UserChangePasswordEvent event) { System.out.println("收到事件:" + event); System.out.println("开始执行业务操作生成关键日志。用户userId为:" + event.getUserId()); } @EventListener({ UserChangePasswordEvent.class }) public void messageListener(UserChangePasswordEvent event) { System.out.println("收到事件:" + event); System.out.println("开始执行业务操作给用户发送短信。用户userId为:" + event.getUserId()); } }3、 @TransactionalEventListener来定义一个监听器,他与@EventListener不同的就是@EventListener标记一个方法作为监听器,他默认是同步执行,如果发布事件的方法处于事务中,那么事务会在监听器方法执行完毕之后才提交事件发布之后就由监听器去处理,而不要影响原有的事务,也就是说希望事务及时提交我们就可以使用该注解来标识注意此注解需要spring-tx的依赖;
// 在这个注解上面有一个注解:@EventListener,所以表明其实这个注解也是个事件监听器。 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @EventListener public @interface TransactionalEventListener { /** * 这个注解取值有:BEFORE_COMMIT(指定目标方法在事务commit之前执行)、AFTER_COMMIT(指定目标方法在事务commit之后执行)、 * AFTER_ROLLBACK(指定目标方法在事务rollback之后执行)、AFTER_COMPLETION(指定目标方法在事务完成时执行,这里的完成是指无论事务是成功提交还是事务回滚了) * 各个值都代表什么意思表达什么功能,非常清晰, * 需要注意的是:AFTER_COMMIT + AFTER_COMPLETION是可以同时生效的 * AFTER_ROLLBACK + AFTER_COMPLETION是可以同时生效的 */ TransactionPhase phase() default TransactionPhase.AFTER_COMMIT; /** * 表明若没有事务的时候,对应的event是否需要执行,默认值为false表示,没事务就不执行了。 */ boolean fallbackExecution() default false; /** * 这里巧妙的用到了@AliasFor的能力,放到了@EventListener身上 * 注意:一般建议都需要指定此值,否则默认可以处理所有类型的事件,范围太广了。 */ @AliasFor(annotation = EventListener.class, attribute = "classes") Class<?>[] value() default {}; /** * The event classes that this listener handles. * <p>If this attribute is specified with a single value, the annotated * method may optionally accept a single parameter. However, if this * attribute is specified with multiple values, the annotated method * must <em>not</em> declare any parameters. */ @AliasFor(annotation = EventListener.class, attribute = "classes") Class<?>[] classes() default {}; /** * Spring Expression Language (SpEL) attribute used for making the event * handling conditional. * <p>The default is {@code ""}, meaning the event is always handled. * @see EventListener#condition */ @AliasFor(annotation = EventListener.class, attribute = "condition") String condition() default ""; /** * An optional identifier for the listener, defaulting to the fully-qualified * signature of the declaring method (e.g. "mypackage.MyClass.myMethod()"). * @since 5.3 * @see EventListener#id * @see TransactionalApplicationListener#getListenerId() */ @AliasFor(annotation = EventListener.class, attribute = "id") String id() default ""; }使用方式如下。phase事务类型,value指定事件。
/** * @Description 事件监听器 * @ClassName LogListener **/ @Component public class ListenerEvent { @EventListener({ UserChangePasswordEvent.class }) public void logListener(UserChangePasswordEvent event) { System.out.println("收到事件:" + event); System.out.println("开始执行业务操作生成关键日志。用户userId为:" + event.getUserId()); } @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT,value = { UserChangePasswordEvent.class }) public void messageListener(UserChangePasswordEvent event) { System.out.println("收到事件:" + event); System.out.println("开始执行业务操作给用户发送短信。用户userId为:" + event.getUserId()); } }如何发布一个事件
@SpringBootTest class SpirngEventApplicationTests { @Autowired ApplicationEventPublisher appEventPublisher; @Test void contextLoads() { appEventPublisher.publishEvent(new UserChangePasswordEvent("1111111")); } }我们执行一下看一下接口。
@EnableAsync @SpringBootApplication public class SpirngEventApplication { public static void main(String[] args) { SpringApplication.run(SpirngEventApplication.class, args); } }2、 在我们想要异步执行的监听器上添加@Async注解;
/** * @Description 事件监听器 * @ClassName LogListener **/ @Component public class ListenerEvent { @Async @EventListener({ UserChangePasswordEvent.class }) public void logListener(UserChangePasswordEvent event) { System.out.println("收到事件:" + event); System.out.println("开始执行业务操作生成关键日志。用户userId为:" + event.getUserId()); } }这样我们的异步执行监听器的业务操作就完成了。