TransactionSynchronizationManager
/**
* 在事务方法中,调用该方法。提交事务后,才会执行该方法
*
* @author edoup
* @since 1.0.0
*/
@Component
public class CallBackService {
public void execute(Runnable action) {
//判断是否开启了事务
if (TransactionSynchronizationManager.isActualTransactionActive()) {
//将操作注册到“afterCommit”(事务提交之后)
TransactionSynchronizationManager
.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
// 事务提交后执行回调
action.run();
}
});
//没有开启事务的直接执行
} else {
action.run();
}
}
}
使用举栗:等待同步数据的事务方法执行完毕后,执行其他方法操作这些人员数据
public class PersonResourceSyncService implements IResourceIrdsSync {
@Autowired
private CallBackService callBackService;
@Autowired
private IPersonUncheckDailyService personUncheckDailyService;
@Override
public String getResourceType() {
return ResourceTypeEnum.PERSON.getResourceType();
}
//开启了事务
@Transactional(rollbackFor = Exception.class)
@Override
public void syncAll(List<HashMap> resList) {
//中间省略部分代码
//删除不存在的数据
this.delete(deletePersonIds);
//插入新数据
this.doAdd(addPersonList);
//更新老数据
this.doUpdate(updatePersonList);
log.info(LogFormatter.toMsg("syncAll person end..."));
callBackService.execute(()->{
//初始化今天未检测人员
personUncheckDailyService.initPersonCheckStatusToday();
});
}
ApplicationEventPublisher
假设一个需求:中间需要先操作数据库,如果返回成功,在将结果发送到mq。如果方法不加事务,数据库操作失败可能造成脏数据,如果加了事务,必须保证在事务失败时,发送目前消息的方法不会执行。
@Service
public class MessageSenderServiceImpl implements IMessageSenderService{
// 注入ApplicationEventPublisher
@Autowired
private ApplicationEventPublisher publisher;
@Override
public void sendMessage(String type, String message) throws Exception {
//省略部分代码
//调用publishEvent方法,发布事件。将需要传递的参数放入其中。
publisher.publishEvent(new MessageDTO(type, message));
}
}
新建一个类,类中方法加上@TransactionalEventListener注解即可
参数类型MessageDTO 与上面对应即可,事务执行成功会自动调用。
@Component
public class TransactionalMessageListener {
Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
IMessageSenderService messageSenderService;
@TransactionalEventListener(fallbackExecution = true,phase=TransactionPhase.AFTER_COMMIT)//AFTER_COMMIT是事务提交后执行,默认就是这个
//fallbackExecution=true则会在没有事务时也执行该方法,不然只有加上事务才会监听,切记。默认是false
//参数类型MessageDTO 与上面对应即可,事务执行成功会自动调用。
public void handleMessageSend(MessageDTO message) throws Exception{
logger.info("***********************messageListener************************");
logger.info("messageType:"+message.getMessageType());
logger.info("messageContent"+message.getMessageContent());
//发送消息到mq
messageSenderService.sendMessage(message.getMessageType(), uuid, message.getMessageContent());
}
}
ApplicationEvent 实现解耦
public class TestEvent extends ApplicationEvent {
private String name;
private String msg;
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public TestEvent(Object source,String name,String msg) {
super(source);
this.name = name;
this.msg = msg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
**
*
* 事件监听器
* @author edoup
* @since 1.0.0
*/
@Component
public class TestEventListener implements ApplicationListener<TestEvent> {
/**
* 重写事件监听方法
* @param event
*/
@Async
@Override
public void onApplicationEvent(TestEvent event) {
System.out.println("姓名:" + event.getName() + "得到消息:" + event.getMsg());
}
}
/**
*
* 发布事件测试
* @author edoup
* @since 1.0.0
*/
@RestController
@RequestMapping
public class TestController {
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/test")
public void test() {
TestEvent event = new TestEvent(this,"张三","消息");
applicationContext.publishEvent(event);
}
}