服务内部的弹簧@Async方法

2022-09-02 00:23:34

我有这个服务bean,它有一个调用内部异步方法的sync方法:

@Service
public class MyService {
    
    public worker() {
        asyncJob();
    }
    
    @Async
    void asyncJob() {
        ...
    }
    
}

麻烦的是,实际上并没有以异步方式调用 。我发现这不起作用,因为内部调用跳过了AOP代理asyncJob

所以我试着自我推荐豆子:

@Service
public class MyService {
    
    MyService mySelf;

    @Autowired
    ApplicationContext cnt;

    @PostConstruct
    public void init() {
        mySelf=(MyService)cnt.getBean("myService");
    }
    
    
    public void worker() {
        mySelf.asyncJob();
    }
    
    @Async
    void asyncJob() {
        ...
    }
    
}

它失败了。同样没有异步调用。

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

@Service
public class MyService {

    @Autowired
    MyAsyncService myAsyncService;

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

@Service
public class MyAsyncService {

    @Async
    void asyncJob() {
        ...
    }
    
}

再次失败


唯一的工作方式是从控制器 Bean 调用它:

@Controller
public class MyController {

    @Autowired
    MyAsyncService myAsyncService;

    @RequestMapping("/test")
    public void worker() {
        myAsyncService.asyncJob();
    }

}

@Service
public class MyAsyncService {

    @Async
    public void asyncJob() {
        ...
    }
    
}

但在这种情况下,这是一项服务工作。为什么我无法从服务调用它?


答案 1

找到了一个非常好的方法来解决这个问题(使用java8),在你有很多想要同步和异步的各种事情的情况下。与其为每个“同步”服务创建单独的服务,不如创建一个通用的异步服务包装器:XXXAsync

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

}

答案 2

我解决了第三种方法(将其分成两个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
        ...
    }

}

推荐