服务中的Spring @Async方法

时间:2014-07-17 08:39:01

标签: java spring spring-mvc asynchronous

我有一个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(){
        ...
    }

}

但在这种情况下,这是一项服务工作......为什么我不能从服务中调用它?

3 个答案:

答案 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;

    }