我有一个Service bean,调用内部异步方法的同步方法:
@Service
public class MyService {
public worker(){
asyncJob();
}
@Async
asyncJob(){
...
}
}
麻烦的是asyncJob实际上不是以异步方式调用。 我发现这不起作用,因为内部调用会跳过 AOP代理。
所以我尝试自我引用 bean:
@Service
public class MyService {
MyService mySelf;
@Autowired
ApplicationContext cnt;
@PostConstruct
public init(){
mySelf=(MyService)cnt.getBean("myService");
}
public worker(){
mySelf.asyncJob();
}
@Async
asyncJob(){
...
}
}
失败。再也没有异步电话。
所以我尝试在两个bean中除以:
@Service
public class MyService {
@Autowired
MyAsyncService myAsyncService;
public worker(){
myAsyncService.asyncJob();
}
}
@Service
public class MyAsyncService {
@Async
asyncJob(){
...
}
}
再次失败。
唯一可行的方法是从 Controller Bean :
调用它@Controller
public class MyController {
@Autowired
MyAsyncService myAsyncService;
@RequestMapping("/test")
public worker(){
myAsyncService.asyncJob();
}
}
@Service
public class MyAsyncService {
@Async
public asyncJob(){
...
}
}
但在这种情况下,这是一项服务工作......为什么我不能从服务中调用它?
答案 0 :(得分:24)
找到一个非常好的方法来解决这个问题(使用java8),在这种情况下,你有很多想要同步和异步的东西。而不是为每个同步'创建单独的XXXAsync
服务。 service,创建一个通用的异步服务包装器:
@Service
public class AsyncService {
@Async
public void run(final Runnable runnable) {
runnable.run();
}
}
然后使用它:
@Service
public class MyService {
@Autowired
private AsyncService asyncService;
public void refreshAsync() {
asyncService.run(this::refresh);
}
public void refresh() {
// my business logic
}
public void refreshWithParamsAsync(String param1, Integer param2) {
asyncService.run(() -> this.refreshWithParams(param1, param2));
}
public void refreshWithParams(String param1, Integer param2) {
// my business logic with parameters
}
}
答案 1 :(得分:3)
我解决了第三种方法(将其划分为两个bean)将异步方法修饰符切换为 public
@Service
public class MyService {
@Autowired
MyAsyncService myAsyncService;
public worker(){
myAsyncService.asyncJob();
}
}
@Service
public class MyAsyncService {
@Async
public asyncJob(){ // switched to public
...
}
}
答案 2 :(得分:0)
就我而言,删除@Async
批注并直接使用taskExecutor
来提交我的任务比较容易:
之前
@Async("taskExecutor")
private Future<U> executerEnAsync(
final T pInput) {
final U resultat = this.appelerBS(pInput);
return new AsyncResult<U>(resultat);
}
之后
@Autowired
private AsyncTaskExecutor taskExecutor;
private Future<U> executerEnAsync(
final T pInput) {
final Future<U> future = taskExecutor.submit(new Callable<U>() {
@Override
public U call() {
final U resultat = appelerBS(pInput);
return resultat;
}
});
return future;
}