2017-12-09 9 views
0

私はSpringのプロキシの作成方法に問題があると考えています。なぜSpring AOPのアスペクトを追加すると、Springコンテキストの初期化中にこの非同期呼び出しが中断されますか?

この最小限の例では、私はの2つのクラスAccountLoaderBankImplを実装しています。起動時に、AccountLoaderは、自動呼び出しBank -instanceへのいくつかの同時呼び出しを実行します。BankImplのメソッドにはアスペクトが指定されています。

この設定では、コールが終了しないように見えるので、未完了コール(Future.get)はTimeoutExceptionで終了します。ただし、呼び出し元がexecutorに送信される前に同じメソッドを呼び出すと、すべての呼び出しが正常に終了します。

ここで春とは何が起こっていますか?なぜこの非同期呼び出しは終了しないのですか?そしてなぜ非同期呼び出しの前に同期呼び出しを追加すれば、7つの地獄でそれが終わるのですか?

あなたは以下のコードを見つけることができ、完全な作業例もavailable on Github

public interface Bank { 

    Map<String, String> getAccounts(String q); 

} 

さのために単純な実装

@Service 
public class BankImpl implements Bank { 

    private static final Logger LOGGER = LoggerFactory.getLogger(BankImpl.class); 

    @Override 
    public Map<String, String> getAccounts(String q) { 
     LOGGER.info("Listing accounts for {}", q); 
     return Collections.singletonMap(q, "q"); 
    } 

} 

そして最後に、発信者

@Service 
public class AccountLoader { 

    private static final Logger LOGGER = LoggerFactory.getLogger(AccountLoader.class); 
    private final ExecutorService executorService = Executors.newSingleThreadExecutor(); 

    @Autowired 
    private Bank bank; 

    @PostConstruct 
    public void refresh() { 
     LOGGER.info("Refreshing accounts"); 
     // Uncommenting the following line will let the calls terminate 
     // bank.getAccounts("sync"); 
     try { 
      executorService.submit(() -> { bank.getAccounts("async"); }) 
       .get(5L, TimeUnit.SECONDS); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 

    } 

} 

です完全性、ここには、アスペクト

@Aspect 
@Component 
public class SomeAspect { 

    private static final Logger LOGGER = LoggerFactory.getLogger(SomeAspect.class); 

    @AfterReturning(pointcut = "execution(* com.github.mtritschler.aspects.BankImpl.getAccounts(..))", returning = "returnValue") 
    public Map<String, String> logCallee(Map<String, String> returnValue) { 
     LOGGER.info("Result is {}", returnValue); 
     return returnValue; 
    } 

} 

と最後ではなく、少なくとも設定

@EnableAspectJAutoProxy 
@Configuration 
public class MyConfig { 
} 

アップデート:私は@EnableAspextJAutoProxyを削除した場合、私は例外を得ることはありません。積み込み時間に切り替えても何も変わりませんでした。

答えて

0

メインスレッドのアプリケーション初期化と注入された依存関係への同時アクセスの競合状態が発生していました。

ContextRefreshedEventのリスナーのために@PostConstructを交換したところ、うまくいきました。

関連する問題