spring 为什么在这个方法中忽略了@ translation注解?

igetnqfo  于 4个月前  发布在  Spring
关注(0)|答案(2)|浏览(51)

我在尝试将@ translation注解应用于同一个类(MyService)中的方法(methodC())时遇到了这个问题。尽管使用了注解,事务似乎没有按预期创建。

@Service
public class MyService {

  @Autowired
  private Service1 service1;

  @Autowired
  private Service2 service2;

  @Override
  public void methodA() {
    methodB();
  }

  private void methodB() {
    try{  
      methodC();
    }catch(MyException e){
      System.out.println(e);
    }catch(Exception e){
      System.out.println(e);
    }
  }

  @Transactional
  public void methodC() throws MyException, Exception{
    try{
      service1.someDeleteAndInserts();
      service2.someDeleteAndInserts();
    }catch(MyException e){
      throw e;
    }catch(Exception e){
      throw e;
    }
    
  }
}

字符串
就像我现在所做的,它为每个方法单独创建一个事务,我希望它只为该方法中调用的所有方法创建一个事务。

@Transactional
  public void methodC() throws MyException, Exception{
    try{
      service1.someDeleteAndInserts();
      service2.someDeleteAndInserts();
    }catch(MyException e){
      throw e;
    }catch(Exception e){
      throw e;
    }
    
  }

o4hqfura

o4hqfura1#

你不能在同一个服务中调用带@Transactional注解的方法。你只能从服务外部调用它,否则不会创建任何transaction。每个spring服务都是一个代理,transactions(AOP)是在代理上创建的,所以一旦你输入任何方法,你就不再在代理中了,所以没有AOP(没有transactions)。
注意事项:但是你可以把@Transactional放在methodA()上来创建一个transaction,但是transaction会在你调用它的时候就开始,而不是在它到达methodC的时候,而且任何transaction异常都会传播到你调用methodA()的地方,而不是methodC()
例如,如果您有:

@Service
public class Service1 {

    @Transactional
    public void method1() { ... }

    public void method2() {
        method1();
    }
}

@Service
public class Service2 {

    @Autowired
    private Service1 service1;

    public void method1() {
        service1.method1();
    }

    public void method2() {
        service1.method2();
    }
}

字符串

  • 调用service1.method2()创建事务。
  • 调用service1.method1()将创建一个。
  • 调用service2.method2()创建事务。
  • 调用service2.method1()将创建一个。

因为Spring处理代理和AOP的方式。

hvvq6cgz

hvvq6cgz2#

正如其他的答案和评论所指出的,你必须跨代理边界调用它才能工作,这同样适用于其他注解,比如@Cacheable
有一个小技巧可以让它工作,那就是将服务的一个示例自动装配到它自己中,并在注入的版本上调用该方法。

@Service
 // 1. Set the proxy mode to TARGET_CLASS
 @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
 public class MyService {

   // 2. Autowire an instance of the service into itself
   @Autowired
   private MyService self;

   private void methodB() {
     try{
       // 3. Call methodC through your injected version
       self.methodC();
     }catch(MyException e){
       System.out.println(e);
     }catch(Exception e){
       System.out.println(e);
     }
   }
 }

字符串
现在,当您使用注入的服务调用methodC时,它将参与事务。

相关问题