如果我在 spring-boot 中以服务级别提供 @Async,它就无法工作
@Async is not working if I give it at service level in spring-boot
我正在控制器中自动装配服务。在服务中,我有一个场景,我需要抛出异常并且数据库也发生变化。所以,我尝试了@Async
@Transactional
public void verifyOtp(OtpDto otpDto)
...
if(xyz){
deactivateOtp(emp.getId());
throw new ServException("Mobile no requested is already assigned", "error-code");
}
}
@Async
@Transactional //with or without
public void deactivateOtp(Integer id){
otpRepo.deactivateOtp(id);
}
public interface OtpRepository extends JpaRepository<Otp, Integer> {
@Modifying
@Query("UPDATE Otp SET isActive = 0 WHERE id = :id")
public void deactiveOtp(@Param("id") Integer id);
这不是在创建新线程。但是,如果我在回购协议中提供,它会起作用
public void deactivateOtp(Integer id){
otpRepo.deactivateOtp(id);
}
public interface OtpRepository extends JpaRepository<Otp, Integer> {
@Async
@Transactional
@Modifying
@Query("UPDATE Otp SET isActive = 0 WHERE id = :id")
public void deactiveOtp(@Param("id") Integer id);
这个问题讨论了很多次。
基本上,SpringAOP不会拦截本地方法调用
(在你的情况下,在同一个 class 中调用 deactivateOtp()
)
您可以在此处阅读有关此行为的更多信息:Understanding AOP proxies
亮点:
The key thing to understand here is that the client code inside the main(..) of the Main class has a reference to the proxy. This means that method calls on that object reference will be calls on the proxy, and as such the proxy will be able to delegate to all of the interceptors (advice) that are relevant to that particular method call. However, once the call has finally reached the target object, the SimplePojo reference in this case, any method calls that it may make on itself, such as this.bar() or this.foo(), are going to be invoked against the this reference, and not the proxy. This has important implications. It means that self-invocation is not going to result in the advice associated with a method invocation getting a chance to execute.
首先检查服务是否被包裹到代理中(你可以在控制器中放置一个断点并查看对服务的引用,它将与代理一起)。否则配置有问题,@Transactional/@Async
将无法工作,直到你修复它。
现在,假设这不是问题,代码中就有问题:
当控制器调用 service.verifyOtp
时,它会转到代理(处理事务),然后转到您的实现。
但是当它到达你的实现时,你调用属于同一个impl的方法,它不会再次通过代理,而是直接进入deactivateOtp
,就好像没有spring 在这里。当然,@Async
不行。
分辨率方面:
如果您使用 spring 4.3+,请考虑使用自我注入。阅读 this thread 了解更多信息。
或者,重构您的代码,使 deactivateOtp
成为另一个 class 的 public 方法。在这种情况下,调用将不再是 "internal",它将通过代理路径,因此 @Async
将起作用。
我正在控制器中自动装配服务。在服务中,我有一个场景,我需要抛出异常并且数据库也发生变化。所以,我尝试了@Async
@Transactional
public void verifyOtp(OtpDto otpDto)
...
if(xyz){
deactivateOtp(emp.getId());
throw new ServException("Mobile no requested is already assigned", "error-code");
}
}
@Async
@Transactional //with or without
public void deactivateOtp(Integer id){
otpRepo.deactivateOtp(id);
}
public interface OtpRepository extends JpaRepository<Otp, Integer> {
@Modifying
@Query("UPDATE Otp SET isActive = 0 WHERE id = :id")
public void deactiveOtp(@Param("id") Integer id);
这不是在创建新线程。但是,如果我在回购协议中提供,它会起作用
public void deactivateOtp(Integer id){
otpRepo.deactivateOtp(id);
}
public interface OtpRepository extends JpaRepository<Otp, Integer> {
@Async
@Transactional
@Modifying
@Query("UPDATE Otp SET isActive = 0 WHERE id = :id")
public void deactiveOtp(@Param("id") Integer id);
这个问题讨论了很多次。
基本上,SpringAOP不会拦截本地方法调用
(在你的情况下,在同一个 class 中调用 deactivateOtp()
)
您可以在此处阅读有关此行为的更多信息:Understanding AOP proxies
亮点:
The key thing to understand here is that the client code inside the main(..) of the Main class has a reference to the proxy. This means that method calls on that object reference will be calls on the proxy, and as such the proxy will be able to delegate to all of the interceptors (advice) that are relevant to that particular method call. However, once the call has finally reached the target object, the SimplePojo reference in this case, any method calls that it may make on itself, such as this.bar() or this.foo(), are going to be invoked against the this reference, and not the proxy. This has important implications. It means that self-invocation is not going to result in the advice associated with a method invocation getting a chance to execute.
首先检查服务是否被包裹到代理中(你可以在控制器中放置一个断点并查看对服务的引用,它将与代理一起)。否则配置有问题,@Transactional/@Async
将无法工作,直到你修复它。
现在,假设这不是问题,代码中就有问题:
当控制器调用 service.verifyOtp
时,它会转到代理(处理事务),然后转到您的实现。
但是当它到达你的实现时,你调用属于同一个impl的方法,它不会再次通过代理,而是直接进入deactivateOtp
,就好像没有spring 在这里。当然,@Async
不行。
分辨率方面:
如果您使用 spring 4.3+,请考虑使用自我注入。阅读 this thread 了解更多信息。
或者,重构您的代码,使
deactivateOtp
成为另一个 class 的 public 方法。在这种情况下,调用将不再是 "internal",它将通过代理路径,因此@Async
将起作用。