2016-04-05 13 views
5

私は春の再試行を試みており、私は奇妙な問題に直面しています。レストコントローラ内のメソッドで再試行注釈を使用すると、再試行は機能しません。しかし、そのメソッドを別のサービスクラスに移すと、それは機能します。 Springの再試行がRestControllerで機能しない

@RestController 
public class HelloController { 

    @RequestMapping(value = "/hello") 
    public String hello() { 
     return getInfo(); 
    } 

    @Retryable(RuntimeException.class) 
    public String getInfo() { 
     Random random = new Random(); 
     int r = random.nextInt(2); 
     if (r == 1) { 
      throw new RuntimeException(); 
     } else { 
      return "Success"; 
     } 
    } 
} 
をしかし、次のことを行います:次のコードは動作しないコントローラで使用された場合 @Retryableが機能しない理由

@RestController 
public class HelloController { 

    @Autowired 
    private SomeService service; 

    @RequestMapping(value = "/hello") 
    public String hello() { 
     String result = service.getInfo(); 
     return result; 
    } 
} 

@Service 
public class SomeService { 

    @Retryable(RuntimeException.class) 
    public String getInfo() { 
     Random random = new Random(); 
     int r = random.nextInt(2); 
     if (r == 1) { 
      throw new RuntimeException(); 
     } else { 
      return "Success"; 
     } 
    } 
} 

私の質問はありますか?

答えて

4

表示されている問題は、getInfo()メソッドを呼び出す方法によるものです。

最初の例では、同じスプリングマネージドBeanからgetInfo()を呼び出しています。 2番目の例では、別のスプリングマネージドBeanからgetInfo()を呼び出しています。この区別は微妙ですが、非常に重要です。あなたの問題を引き起こしている可能性が非常に高いです。

@Retryable注釈を使用すると、Springは特殊な状況で特別な処理を行うことができるように、元のBeanの周囲にプロキシを作成しています。この特定のケースでは、Springは、あなたの実際のメソッドに呼び出しを委譲するAdviceを適用し、注釈の設定に従って、RuntimeExceptionがスローしてメソッドの呼び出しを再試行します。

このプロキシがあなたのケースで重要な理由は、外部の発信者だけがプロキシのアドバイスを参照することです。あなたのbeanはそれがプロキシされていることを知りませんし、そのメソッドが(プロキシのアドバイスによって)呼び出されていることだけを知っています。 Beanがそれ自身のメソッドを呼び出すとき、それ以上のプロキシ処理は必要ありません。そのため、実際には再試行は行われません。

関連する問題