简体   繁体   English

在@Transactional方法之前和之后执行代码

[英]Executing code before and after @Transactional method

We have a Spring based application with a service layer which is annotated with @Transactional.我们有一个基于 Spring 的应用程序,其服务层使用@Transactional 进行注释。 We need to have code run before and after some transactional methods for the following reasons:我们需要在一些事务方法之前和之后运行代码,原因如下:

  1. We need to synchronize access to the method based on a key.我们需要根据一个键来同步对方法的访问。 The thread needs to block before the start of the transaction.线程需要在事务开始之前阻塞。
  2. We need to post a message on a queue if the transaction succeeds.如果事务成功,我们需要在队列上发布消息。

The options seem to be:选项似乎是:

  1. Create a class with similar methods to the service that can run the @Transactional method in a synchronized block and check for the return then post the message (would need a separate class due to AOP proxy problem).使用与服务类似的方法创建一个 class,该服务可以在同步块中运行 @Transactional 方法并检查返回然后发布消息(由于 AOP 代理问题,需要单独的 class)。 Services calling services, not nice, feels like a work-around.服务调用服务,不是很好,感觉像是一种变通方法。
  2. Write an aspect to wrap around the @Transactional AOP which can do the synchronization and message posting.编写一个方面来包装@Transactional AOP,它可以进行同步和消息发布。 Might work but would rather avoid AOP.可能有效,但宁愿避免 AOP。
  3. Move the transaction down to the domain layer.将事务向下移动到域层。 Not desirable or possibly even feasible with the current implementation due to the way domain methods are reused in different workflows.由于域方法在不同的工作流中重用的方式,当前的实现是不可取的,甚至可能不可行。
  4. Code the transaction by hand in the service method and scrap @Transactional.在服务方法中手动编码事务并废弃@Transactional。

I would imagine this is a fairly common requirement.我想这是一个相当普遍的要求。 Probably I am missing an option 5, which is the obvious one!可能我错过了选项 5,这是显而易见的选项!

I think I'd go with 2 unless you have some specific reasons to avoid AOP.我想我会用 2 go 除非你有一些具体的理由来避免 AOP。 Your problem is a classic example of where AOP can be used and it looks pretty good in the result.您的问题是可以使用 AOP 的经典示例,结果看起来相当不错。 Here is a nice example of how to implement that (if you didn't read that already): Advising transactional operations这是一个很好的例子来说明如何实现它(如果你还没有读过): Advising transactional operations

If AOP is really not an option, I'd go the 'Otherwise' option proposed by @Lawrence McAlpin.如果 AOP 真的不是一个选项,我会 go @Lawrence McAlpin 提出的“否则”选项。

Check out TransactionSynchronization callback interface.查看TransactionSynchronization回调接口。 Spring can natively inform you what is happening with your transaction. Spring 可以本地通知您交易发生了什么。

I would use a TransactionTemplate (your option 4) and programatically control the scope of the transaction in situations like this.在这种情况下,我会使用TransactionTemplate (您的选项 4)并以编程方式控制事务的 scope。

Otherwise, you could move the logic in your method out into a separate service, make that new service @Transactional, remove the @Transactional from the current method, and then surround the call to the new service with your pre- and post-transaction logic.否则,您可以将方法中的逻辑移到单独的服务中,将该新服务设置为 @Transactional,从当前方法中删除 @Transactional,然后使用您的事务前和事务后逻辑围绕对新服务的调用. I've taken this approach as well, but I prefer programmatic transaction management for requirements like this, as I think it's cleaner and, as you mentioned, services calling services (that are only ever needed by the first service) just feels like a hackish workaround.我也采用了这种方法,但是对于这样的需求,我更喜欢程序化事务管理,因为我认为它更干净,而且,正如您所提到的,服务调用服务(只有第一个服务需要)感觉就像是 hackish解决方法。

if the key is being passed as part of the method call, then you can use java ReentrantLock to do the job.. its much simpler & cleaner.如果密钥作为方法调用的一部分传递,那么您可以使用 java ReentrantLock来完成这项工作。它更简单、更干净。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM