如何在Springboot中将@Async与@Scheduled注释一起使用?

Har*_*ngh 3 java spring spring-mvc scheduled-tasks spring-boot

我想将@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
Run Code Online (Sandbox Code Playgroud)

Pav*_*nov 6

该错误为您提供了建议:

方法“ 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 {
....
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

通过在配置中强制使用代理目标类模式来切换到CGLIB代理

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

@EnableAspectJAutoProxy(proxyTargetClass = true)
Run Code Online (Sandbox Code Playgroud)

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


Ank*_*ogi -1

根据错误堆栈,它表示将方法移至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. 
Run Code Online (Sandbox Code Playgroud)