在@Scheduled方法中调用Spring @Async方法

时间:2017-04-04 10:37:01

标签: java spring spring-boot spring-async

我使用@EnableScheduling@EnableAsync进行Spring启动。

我有一个用@Scheduled注释的方法。 我还有一些方法,用@Async注释。

现在我在@Async方法中调用这些@Scheduled方法,并在异步方法中打印出当前线程的名称。我看到的是它们都有相同的线程名称,实际上它是运行@Scheduled方法的线程。

我没有看到异步方法执行。 这有什么不对?

这是我的应用程序启动类

@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());
    }
}

输出

方法一由Thread调用:pool-1-thread-1在Tue Apr 04 16:32:27 IST 2017

方法二由Thread调用:pool-1-thread-1在Tue Apr 04 16:32:27 IST 2017

方法三由Thread调用:pool-1-thread-1在Tue Apr 04 16:32:27 IST 2017

2 个答案:

答案 0 :(得分:11)

<强>解释

Spring在您的实例周围创建代理。 ScheduledMethod内部调用3个方法,这些方法未被代理,因此不是异步的。

cf. the documentation

  

如果在对象引用上调用方法,则调用该方法   直接在该对象引用上,如下所示。

请参阅此问题Spring AOP not working, when the method is called internally within a bean 以获取解决方法,但最好的是文档The best approach (the term best is used loosely here) is to refactor your code such that the self-invocation does not happen...

中提出的问题

请注意,私有方法不是supported too

  

由于Spring的AOP框架基于代理的特性,受到保护   根据定义,方法既不被拦截,也不用于JDK代理   (这不适用)也不适用于CGLIB代理(如果是这样的话)   技术上可行,但不建议用于AOP目的)。作为一个   结果,任何给定的切入点都将与公共方法相匹配   只有!

解决方法示例

@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();
    }
}

答案 1 :(得分:4)

您的Thread Pool可能没有为Threads配置更多Scheduler

来自docs

  

如果您不提供pool-size属性,则默认线程池将只有一个线程。