如何在springboot中使用@Async和@Scheduled注释?

时间:2018-06-16 12:44:14

标签: java spring spring-mvc spring-boot scheduled-tasks

我想将@scheduled与@Async注释一起使用,但是当我启动服务器时,我得到了这个异常,如果我删除了@Async注释,它就可以了。任何帮助将不胜感激。

@Component
public class NService  {

@Scheduled(fixedDelay =70*100)
@Async
public void someMethod() throws SQLException {

    //some Processing
}
}

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.IllegalStateException: Need to invoke method 'recordHeartBeat' declared on target class 'NodeStatusService', but not found in any interface(s) of the exposed proxy type. Either pull the method up to an interface or switch to CGLIB proxies by enforcing proxy-target-class mode in your configuration.
at org.springframework.core.MethodIntrospector.selectInvocableMethod(MethodIntrospector.java:135)
at org.springframework.aop.support.AopUtils.selectInvocableMethod(AopUtils.java:130)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.processScheduled(ScheduledAnnotationBeanPostProcessor.java:341)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:324)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:423)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1633)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
... 20 common frames omitted

2 个答案:

答案 0 :(得分:3)

该错误提供了建议:

  

在目标类上声明的方法'recordHeartBeat'   'NodeStatusService',但在暴露的任何接口中都找不到   代理类型。将方法拉到接口或切换到   CGLIB通过强制执行代理目标类模式代理   配置。

要正确运行,@ Async注释需要为您的类创建代理(包装器)。执行顺序为:

  

来电 - >代理方法        - >你的班级方法

Spring可以使用两种方式自动创建代理:

1)通过实现接口

如果一个类实现了一个接口,Spring可以创建一个代理类来实现该接口并将其注入执行路径。这是错误消息中建议的第一部分:

  

将方法拉到界面

要按照这种方式,您需要使用public void recordHeartBeat() throws SQLException创建一个界面并在类中实现您的界面,例如:

public interface HeartBeater {
  void recordHeartBeat() throws SQLException;
}

public class NodeStatusService implements NodeStatus implements HeartBeater {
....
}

2)通过使用CGLIB创建字节码代理

如果某个类没有实现使用@Async注释声明方法的接口,那么Spring可以使用CGLIB创建一个字节码代理。它使用字节码操作来改变调用序列。

这是错误消息中建议的第二部分:

  

通过强制执行代理目标类模式切换到CGLIB代理   构造

您可以通过向配置bean添加注释来启用代理目标类:

@EnableAspectJAutoProxy(proxyTargetClass = true)

请参阅文档以获取示例:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/EnableAspectJAutoProxy.html

答案 1 :(得分:0)

根据错误堆栈,它表示将方法recordHeartBeat()移至NodeStatus界面或使用CGLib proxy

Caused by: java.lang.IllegalStateException: Need to invoke method 'recordHeartBeat' declared on target class 'NodeStatusService', but not found in any interface(s) of the exposed proxy type. Either pull the method up to an interface or switch to CGLIB proxies by enforcing proxy-target-class mode in your configuration.