Метод Spring @Async внутри службы
у меня есть этот компонент службы с методом синхронизации, вызывающим внутренний асинхронный метод:
@Service
public class MyService {
public worker(){
asyncJob();
}
@Async
asyncJob(){
...
}
}
проблема в том, что asyncJob на самом деле не вызывает асинхронным способом. Я обнаружил, что это не работает, потому что внутренний вызов пропускает прокси AOP.
поэтому я стараюсь self-refer Боб:
@Service
public class MyService {
MyService mySelf;
@Autowired
ApplicationContext cnt;
@PostConstruct
public init(){
mySelf=(MyService)cnt.getBean("myService");
}
public worker(){
mySelf.asyncJob();
}
@Async
asyncJob(){
...
}
}
это не. Снова нет асинхронного вызова.
поэтому я попытался разделить в два бобы:
@Service
public class MyService {
@Autowired
MyAsyncService myAsyncService;
public worker(){
myAsyncService.asyncJob();
}
}
@Service
public class MyAsyncService {
@Async
asyncJob(){
...
}
}
Не .
единственный рабочий способ-вызвать его из Контроллер Bean:
@Controller
public class MyController {
@Autowired
MyAsyncService myAsyncService;
@RequestMapping("/test")
public worker(){
myAsyncService.asyncJob();
}
}
@Service
public class MyAsyncService {
@Async
public asyncJob(){
...
}
}
но в этом случае это служебная работа... почему я не могу позвонить ему со службы?
2 ответов
нашел действительно хороший способ решить эту проблему (с 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
}
}
Я решил третий метод (разделите его на два компонента), переключив модификатор асинхронного метода на общественные
@Service
public class MyService {
@Autowired
MyAsyncService myAsyncService;
public worker(){
myAsyncService.asyncJob();
}
}
@Service
public class MyAsyncService {
@Async
public asyncJob(){ // switched to public
...
}
}