@Scheduled 方法中的 Spring @Async 方法调用 [英] Spring @Async method call inside @Scheduled method
问题描述
我正在使用带有 @EnableScheduling
和 @EnableAsync
的 Spring Boot.
I am using Spring boot with @EnableScheduling
and @EnableAsync
.
我有一个用 @Scheduled
注释的方法.我还有几个方法,用 @Async
注释.
I have a method which is annotated with @Scheduled
.
I have a few more methods, which are annotated with @Async
.
现在我在 @Scheduled
方法中调用这些 @Async
方法并在异步方法中打印出当前线程的名称.我看到的是它们都有相同的线程名称,实际上就是运行 @Scheduled
方法的线程.
Now I am calling these @Async
methods in the @Scheduled
method and printing out the name of the current thread in the async methods. What I see is they all have same thread name, which in fact is the thread that is running the @Scheduled
method.
我没有看到异步方法执行.这里有什么问题?
I don't see asynchronous method execution. What is wrong here?
这是我的应用程序启动类
Here is my application boot class
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class ApplicationBoot {
public static void main(String[] args) {
SpringApplication.run(ApplicationBoot.class, args);
}
}
这是我的调度程序类
@Component
public class TaskScheduler {
private static final Logger logger = Logger.getLogger(TaskScheduler.class);
@Scheduled(fixedDelay = 10000)
public void ScheduledMethod() {
methodOne();
methodTwo();
methodThree();
}
@Async
private void methodOne() {
logger.info("Method one called by Thread : " + Thread.currentThread().getName() + " at " + new Date());
}
@Async
private void methodTwo() {
logger.info("Method two called by Thread : " + Thread.currentThread().getName() + " at " + new Date());
}
@Async
private void methodThree() {
logger.info("Method three called by Thread : " + Thread.currentThread().getName() + " at " + new Date());
}
}
输出
线程调用的方法一:pool-1-thread-1 at Tue Apr 04 16:32:27 IST 2017
Method one called by Thread : pool-1-thread-1 at Tue Apr 04 16:32:27 IST 2017
线程调用的方法二:pool-1-thread-1 at Tue Apr 04 16:32:27 IST 2017
Method two called by Thread : pool-1-thread-1 at Tue Apr 04 16:32:27 IST 2017
线程调用的方法三:pool-1-thread-1 at Tue Apr 04 16:32:27 IST 2017
Method three called by Thread : pool-1-thread-1 at Tue Apr 04 16:32:27 IST 2017
推荐答案
说明
Spring 在您的实例周围创建一个代理.ScheduledMethod
在内部调用 3 个方法,它们没有被代理,因此不是异步的.
Spring creates a proxy around your instance. ScheduledMethod
calls internally 3 methods, which are not proxified and thus not asynchronous.
参见文档:
如果在对象引用上调用方法,则调用该方法直接在该对象引用上,如下所示.
If you invoke a method on an object reference, the method is invoked directly on that object reference, as can be seen below.
看这个问题Spring AOP 不起作用,当该方法在 bean 内部被调用时 一种解决方法,但最好的是文档中提出的方法
See this question Spring AOP not working, when the method is called internally within a bean
for a workaround, but the best is the one proposed in the doc The best approach (the term best is used loosely here) is to refactor your code such that the self-invocation does not happen...
请注意,私有方法不是 也支持:
Note that, private method is not supported too:
由于 Spring 的 AOP 框架基于代理的特性,保护根据定义,方法不会被拦截,对于 JDK 代理也不会(如果这不适用)也不适用于 CGLIB 代理(如果这是技术上可行但不推荐用于 AOP 目的).作为结果,任何给定的切入点都将与公共方法匹配只有!
Due to the proxy-based nature of Spring’s AOP framework, protected methods are by definition not intercepted, neither for JDK proxies (where this isn’t applicable) nor for CGLIB proxies (where this is technically possible but not recommendable for AOP purposes). As a consequence, any given pointcut will be matched against public methods only!
解决方法示例
@Component
public class ServiceMethod {
private static final Logger logger = Logger.getLogger(ServiceMethod .class);
@Async
public void methodOne() {
logger.info("Method one called by Thread : " + Thread.currentThread().getName() + " at " + new Date());
}
@Async
public void methodTwo() {
logger.info("Method two called by Thread : " + Thread.currentThread().getName() + " at " + new Date());
}
@Async
public void methodThree() {
logger.info("Method three called by Thread : " + Thread.currentThread().getName() + " at " + new Date());
}
}
@Component
public class TaskScheduler {
private static final Logger logger = Logger.getLogger(TaskScheduler.class);
@Autowired
private ServiceMethod serviceMethod;
@Scheduled(fixedDelay = 10000)
public void ScheduledMethod() {
serviceMethod.methodOne();
serviceMethod.methodTwo();
serviceMethod.methodThree();
}
}
这篇关于@Scheduled 方法中的 Spring @Async 方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!