私はSpringのプロキシの作成方法に問題があると考えています。なぜSpring AOPのアスペクトを追加すると、Springコンテキストの初期化中にこの非同期呼び出しが中断されますか?
この最小限の例では、私はの2つのクラスAccountLoader
とBankImpl
を実装しています。起動時に、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
を削除した場合、私は例外を得ることはありません。積み込み時間に切り替えても何も変わりませんでした。