在springboot项目中,ApplicationEvent的应用会和切面AOP相结合,做一些本身功能以外的事务处理,例如数据同步,在自己系统中,新建只需要将自己的数据插入数据库,而同步数据到另一个系统中就是额外的事务,还能做一些操作验证的事务。最关键是,当一个事件发布(注册),可以被多个监听器监听,执行事务逻辑。
首先我们需要继承ApplicationEvent,将该事务所需的参数封装在一个实体里。
代码示例:
@Slf4j
@Setter
@Getter
public class TempDocumentEvent extends ApplicationEvent {
private String eventName;
private String concent;
//能够避免在多线程使用时候,改变ThreadLocal里的内容不会改变,子线程使用时候,get,set,就不是单独一个ThreadLocal,里面的内容可以让多人同时get,set
public static ThreadLocal
首先还是要了解相关的注解:
1.注解TransactionalEventListener:这是一个springboot4.2版本以上才能使用的注解,这个注解有几个值可以从源码来看一下:一开始我是从源码的注释复制起来翻译的,但觉得不太好,就从网上找到了比较好的说明。
// @since 4.2 显然,注解的方式提供得还是挺晚的,而API的方式第一个版本就已经提供了
// 另外最重要的是,它头上有一个注解:`@EventListener` so
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EventListener //有类似于注解继承的效果
public @interface TransactionalEventListener {
// 这个注解取值有:BEFORE_COMMIT、AFTER_COMMIT、AFTER_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 {};
@AliasFor(annotation = EventListener.class, attribute = "classes")
Class>[] classes() default {};
String condition() default "";
}
使用方式一:
直接使用上面注解,案例如下:classes的值是你要监听的事务类,fallbackExecution可以让事务没有注入时候开始执行
@Component
@Slf4j
public class ESUpdateEventListener {
//监听有新事务注入,开始执行
@TransactionalEventListener(fallbackExecution=true, classes=TempDocumentEvent.class)
@Async
@Order(0)//这里是注意注入的顺序,
public void eventListener(TempDocumentEvent event) {
//这里是自己的逻辑
return;
}
//参数是list的
}
使用方式二:如果springboot的版本过低就只能继承ApplicationListener来实现onApplicationEvent方法
@Component
@Slf4j
public class ESUpdateEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(TempDocumentEvent event) {
//这里是自己的逻辑
}
//参数是list的
}
在你需要该事务处理的方法里,注入
@Autowired
private ApplicationEventPublisher publisher;
然后使用
publisher.publishEvent(new TempDocumentEvent ());
就了,publish的参数就是你自己的事务实体。