我在我的@Transaction
启用类中有一个方法,该方法使用java反射从外部类调用。不幸的是,Spring Transaction不能在这个方法中工作。类如下所示:
@Transactional
public class CartServiceImpl implements CartService {
@Autowired
AnnotatedMethodInvoker annotatedMethodInvoker;
@Override
@VersionedParent
public BasicResponse addCartItem(AddCartItemRequest addCartItemRequest) throws Exception{
String currentMethodName = Thread.currentThread().getStackTrace()[1].getMethodName();
return (BasicResponse)annotatedMethodInvoker.invoke(this, currentMethodName, addCartItemRequest, AddCartItemRequest.class);
}
@VersionedMethod(parentMethod="addCartItem", minimumVersion=Constants.BUILD_VERSION_1_0_1, description="Added Epoch")
private BasicResponse addCartItemWithEpoch(AddCartItemRequest addCartItemRequest){
/***** Implementation detail goes here *****/
}
@VersionedMethod(parentMethod="addCartItem", minimumVersion=Constants.BUILD_VERSION_1_0_2, description="Added Cart filter here")
private BasicResponse addCartItemWithCartFilter(AddCartItemRequest addCartItemRequest){
/***** Implementation detail goes here *****/
}
}
在AnnotatedMethodInvoker
类的invoke()
方法中,我调用了两个private
方法中的一个addCartItemWithEpoch()
&addCartItemWithCartFilter()
.
问题是,当RuntimeException发生时,事务仍在提交,这本质上意味着Spring Transaction在我的私有方法中不起作用。令人惊讶的是,如果我将下面的语句放入我的私有方法中,它将返回true:
TransactionSynchronizationManager.isActualTransactionActive()
我的应用程序目前一直使用Spring AOP事务,它可以无缝地工作。下面的Application-config.xml片段:
<context:annotation-config />
<context:component-scan base-package="com.apraxalpha.dealernews" />
<tx:annotation-driven />
我读过这篇博客,其中建议使用基于AspectJ的Transaction而不是Spring AOP Transaction方法。我对此不是很有信心,因为我的整个应用程序都在使用基于Spring AOP的事务处理。现在只是为了一个单一的实现更改,我不想将所有内容更改为AspectJ事务。1)在我的应用程序中是否存在这样的中间道路,可以同时使用这两种方法?2)是否有其他方法在我的私有方法中使用java反射调用事务?
浏览了其他几个类似问题的帖子:1)调用Spring Bean类的私有方法时Spring事务不工作2)从同一个类中的另一个方法调用一个方法
似乎您要么使用AspectJ而不是Spring AOP来调用bean类方法或如果您不想使用AspectJ而坚持使用Spring AOP,那么对该类进行简单的重构将解决问题,如下所示:
在问题中,方法公共方法addCartItem和实际实现方法(实际上具有实现代码)都在同一个bean类中。考虑创建一个委托类作为这个bean类之上的层,并将公共方法addCartItem放在这个类中。然后将这两个私有方法设置为公共方法,并尝试从委托方法调用bean类方法。