Java 服务中的 Spring @Async 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24798695/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 14:54:20  来源:igfitidea点击:

Spring @Async method inside a Service

javaspringspring-mvcasynchronous

提问by Tobia

I have this Service bean with a sync method calling an internal async method:

我有一个带有调用内部异步方法的同步方法的服务 bean:

@Service
public class MyService {

    public worker(){
        asyncJob();
    }

    @Async
    asyncJob(){
        ...
    }

}

The trouble is that the asyncJob is not really call in async way. I found that this doesn't work because an internal call skips the AOP proxy.

问题是 asyncJob 并不是真正以异步方式调用。我发现这不起作用,因为内部调用跳过了AOP 代理

So I try to self-referthe bean:

所以我尝试自我引用bean:

@Service
public class MyService {

    MyService mySelf;
    @Autowired
    ApplicationContext cnt;
    @PostConstruct
    public init(){
        mySelf=(MyService)cnt.getBean("myService");
    }


    public worker(){
        mySelf.asyncJob();
    }

    @Async
    asyncJob(){
        ...
    }

}

It fails. Again no async call.

它失败了。再次没有异步调用。

So I tryed to divide itin two beans:

所以我试着把它分成两个豆子:

@Service
public class MyService {
    @Autowired
    MyAsyncService myAsyncService;
    public worker(){
        myAsyncService.asyncJob();
    }
}

@Service
public class MyAsyncService {

    @Async
    asyncJob(){
        ...
    }

}

Fails again.

再次失败

The only working way is to call it from a Controller Bean:

唯一可行的方法是从Controller Bean调用它:

@Controller
public class MyController {
    @Autowired
    MyAsyncService myAsyncService;
    @RequestMapping("/test")
    public worker(){
        myAsyncService.asyncJob();
    }
}

@Service
public class MyAsyncService {

    @Async
    public asyncJob(){
        ...
    }

}

But in this case it is a service job... why I can not call it from a Service?

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

采纳答案by Tobia

I solved the third method (divide it in two beans) switching Async method modifier to public

我解决了第三种方法(将其分成两个bean)将Async方法修饰符切换为public

@Service
public class MyService {
    @Autowired
    MyAsyncService myAsyncService;
    public worker(){
        myAsyncService.asyncJob();
    }
}

@Service
public class MyAsyncService {

    @Async
    public asyncJob(){ // switched to public
        ...
    }

}

回答by jlb

Found a really nice way to solve this (with java8) in the case where you have a lot of various things you want to both sync and async. Instead of creating a separate XXXAsyncservice for each 'synchronous' service, create a generic async service wrapper:

找到了一个非常好的方法来解决这个问题(使用 java8),如果你有很多想要同步和异步的东西。不是XXXAsync为每个“同步”服务创建单独的服务,而是创建一个通用的异步服务包装器:

@Service
public class AsyncService {

    @Async
    public void run(final Runnable runnable) {
        runnable.run();
    }
}

and then use it as such:

然后这样使用它:

@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
    }

}