@Scheduled 方法中的 Spring @Async 方法调用 [英] Spring @Async method call inside @Scheduled method

查看:39
本文介绍了@Scheduled 方法中的 Spring @Async 方法调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用带有 @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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆