java - 为什么 Spring Boot 应用程序使用 @Async 注解的方法会崩溃

标签 java spring asynchronous

我正在开发简单的 Spring Boot 应用程序,并希望在其上使用并发线程。为了实现这一点,我在服务方法上使用 @Async 注释,但是当我添加 @Async 注释时 spring DI 崩溃。它在一个线程内没有 @Async 的情况下工作没有问题。为了调用服务方法,我创建了 jUnit 测试。错误日志显示 DI 不起作用,并且找不到服务类的此类 bean。请帮助在 Spring 上使用 @Async 运行多个线程。

<小时/>

编辑 我尝试放入我的测试类 @Autowired 服务接口(interface)而不是它的实现,然后 @Async 方法在其他线程中运行。我应该如何测试我的服务的不同实现?

是并且崩溃了:

@Autowired
CatalogPageServiceImpl catalogPageServiceImpl;

现在不要崩溃:

@Autowired
CatalogPageService catalogPageService;

我的服务接口(interface):

public interface CatalogPageService {
    public void processPagesList(List<CatalogPage> catalogPage);
    public void processPage(CatalogPage catalogPage);
}
<小时/>

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = CLApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public class CatalogPageServiceImplTest {

    @Autowired
    CatalogPageServiceImpl catalogPageServiceImpl;

    @Test
    public void processPageTest(){
        for (int i=0; i<20; i++){
            catalogPageServiceImpl.processPage(
                    new CatalogPage("test url string "+Integer.toString(i)));
        }
    }
}

应用程序类:

@SpringBootApplication
@EnableAsync
@ComponentScan(basePackages = {"org.cl, org.cl.service.location "})
public class CLApplication {

    private static final Logger log = LoggerFactory.getLogger(CLApplication.class);

    @Bean
    public TaskExecutor locationPageExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(20);
        return executor;
    }   

    public static void main(String[] args) {
        log.info("Application main method call");
        try{
            SpringApplication.run(CLApplication.class, args);
        }catch(Throwable t){
            log.error("Unexpected error: ",t);
        }
        log.info("Application main method exit");
    }
}

服务等级:

@Service
public class CatalogPageServiceImpl implements CatalogPageService {

    @Override
    public void processPagesList(List<CatalogPage> catalogPageList) {
        for (CatalogPage catalogPage:catalogPageList){
            processPage(catalogPage);
        }
    }

    @Override
    @Async("locationPageExecutor")
    public void processPage(CatalogPage catalogPage) {
        try {
            Thread.sleep((new Random()).nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("print from Async method "+catalogPage.getUrl());
    }
}

错误日志:

org.springframework.beans.factory.BeanCreationException: Error creating bean wit
h name 'org.cl.service.CatalogPageServiceImplTest': Injection of autowired depen
dencies failed; nested exception is org.springframework.beans.factory.BeanCreati
onException: Could not autowire field: org.cl.service.location.CatalogPageServic
eImpl org.cl.service.CatalogPageServiceImplTest.catalogPageServiceImpl; nested e
xception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No 
qualifying bean of type [org.cl.service.location.CatalogPageServiceImpl] found f
or dependency: expected at least 1 bean which qualifies as autowire candidate fo
r this dependency. Dependency annotations: {@org.springframework.beans.factory.a
nnotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~
[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.7
.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:385) ~[spring-be
ans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.support.DependencyInjectionTestExecutionLis
tener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) ~[sp
ring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.support.DependencyInjectionTestExecutionLis
tener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[sp
ring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.TestContextManager.prepareTestInstance(Test
ContextManager.java:228) ~[spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(S
pringJUnit4ClassRunner.java:230) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflect
iveCall(SpringJUnit4ClassRunner.java:289) [spring-test-4.2.7.RELEASE.jar:4.2.7.R
ELEASE]
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.j
ava:12) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(
SpringJUnit4ClassRunner.java:291) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(Spr
ingJUnit4ClassRunner.java:249) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(Spr
ingJUnit4ClassRunner.java:89) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:
4.12]
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.
jar:4.12]
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.1
2.jar:4.12]
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.
jar:4.12]
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12
.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbac
ks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.2.7.RELEASE.jar:
4.2.7.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallback
s.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-4.2.7.RELEASE.jar:4.
2.7.RELEASE]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.
12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJU
nit4ClassRunner.java:193) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestRef
erence.java:86) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:3
8) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRu
nner.java:459) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRu
nner.java:675) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.
java:382) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner
.java:192) [.cp/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not au
towire field: org.cl.service.location.CatalogPageServiceImpl org.cl.service.Cata
logPageServiceImplTest.catalogPageServiceImpl; nested exception is org.springfra
mework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [
org.cl.service.location.CatalogPageServiceImpl] found for dependency: expected a
t least 1 bean which qualifies as autowire candidate for this dependency. Depend
ency annotations: {@org.springframework.beans.factory.annotation.Autowired(requi
red=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573
) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(Inject
ionMetadata.java:88) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~
[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    ... 26 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No q
ualifying bean of type [org.cl.service.location.CatalogPageServiceImpl] found fo
r dependency: expected at least 1 bean which qualifies as autowire candidate for
 this dependency. Dependency annotations: {@org.springframework.beans.factory.an
notation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNo
SuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans
-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResol
veDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.7.RELEASE.
jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolve
Dependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.7.RELEASE.ja
r:4.2.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545
) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    ... 28 common frames omitted

最佳答案

您的应用程序正在崩溃,因为您在同一类中使用异步方法 (processPage())。 请检查-https://dzone.com/articles/effective-advice-on-spring-async-part-1

在应用程序中使用 @Async 有一些规则:

  1. Async方法的返回类型应该是void
  2. 切勿在调用方方法调用同一类中相同异步方法的同一个类中编写异步方法。
  3. 不应存在 Aop 循环依赖。

请访问-https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/annotation/Async.html

关于java - 为什么 Spring Boot 应用程序使用 @Async 注解的方法会崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38372742/

相关文章:

java - Spring 注解 : @Component works, @Repository 没有

java - Hibernate + Lombok 的 Id 字段的 LazyInitializationException

asynchronous - 编写/转换 Meteor 同步函数

c# - 取消由 ASP.NET 启动的任务

java - 通过文件资源管理器获取文件的路径

spring - 从 Spring 和 Tomcat 中的索引页面重定向

java - Eclipse:使用 Java 类编译 AspectJ 类

c# - 如何在不阻塞主线程的情况下调用同步异步函数?

java - 如何创建多个级别的子类,以便参数属于子类?

java - NoClassDefFoundError : org/testng/TestNG