服务中的Spring @Async方法

Tob*_*bia 13 java spring asynchronous spring-mvc

我有这个Service bean,调用内部异步方法的sync方法:

@Service
public class MyService {

    public worker(){
        asyncJob();
    }

    @Async
    asyncJob(){
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

问题是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(){
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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

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

@Service
public class MyAsyncService {

    @Async
    asyncJob(){
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

再次失败.

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

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

@Service
public class MyAsyncService {

    @Async
    public asyncJob(){
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

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

jlb*_*jlb 26

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

@Service
public class AsyncService {

    @Async
    public void run(final Runnable runnable) {
        runnable.run();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用它:

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

}
Run Code Online (Sandbox Code Playgroud)


Tob*_*bia 9

我解决了第三种方法(将它分成两个 bean)将异步方法的访问修饰符更改为public

@Service
public class MyService {

    @Autowired
    MyAsyncService myAsyncService;

    public void worker() {
        myAsyncService.asyncJob();
    }
}

@Service
public class MyAsyncService {

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

}
Run Code Online (Sandbox Code Playgroud)