当前位置: 首页 > 知识库问答 >
问题:

为什么Spring启动应用程序使用@Async注释方法崩溃

别锐
2023-03-14

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

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

是和崩溃:

@Autowired
CatalogPageServiceImpl catalogPageServiceImpl;

现在不崩溃:

@Autowired
CatalogPageService catalogPageService;

我的服务界面:

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

共有3个答案

傅丁雷
2023-03-14

只需在服务类中添加一个@配置

@Configuration
@Service
public class CatalogPageServiceImpl implements CatalogPageService
高晋
2023-03-14

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

在应用程序中使用@Async的规则很少:

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

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

齐昊焱
2023-03-14

CLApplication上的@ComponentScan注释上的basPackages属性错误:

@ComponentScan(basePackages = {"org.cl, org.cl.service.location "})

这应该是:

@ComponentScan(basePackages = {"org.cl", "org.cl.service.location"})

这两个包应该被指定为两个独立的字符串,而不是一个包名用逗号分隔的字符串。

您也可以指定org.cl,因为Spring也将查看所有子包,所以如果您指定org.clorg.cl.service.location也将被扫描:

@ComponentScan(basePackages = "org.cl")

事实上,由于它是一个Spring Boot应用程序,您可以完全删除@ComponentScan注释,因为@SpringBootApplication注释已经自动包含它(它将扫描类CLApplication所在的包和所有子包)。

 类似资料:
  • 我想把spring注释@Scheduled添加到spring bean中,并在另一个类中的方法中启动task。在spring引用中只有一种启动task的方法--Scheduling-Tasks。如何在没有@SpringBootApplication和Spring Boot运行器的情况下启动它。

  • 我使用的是IntelliJIDEA CE edition(11.0.4)的最新版本。有一件事我在任何地方都找不到,它阻碍了我对Java/Spring的进一步改进。 控制器: 类:导入com.example.demo.interfaces.ISave; 类接口: 没什么特别的,只是为了掌握Spring和Java。 在我的控制器里,当我试图使用 我收到一个阻止应用启动的错误。以下是错误: 任务应用程序

  • 我不明白我的问题在哪里。我的应用程序在启动时崩溃与此崩溃日志。 iOS 7.0。2(11A501)报告版本:104 异常类型: 00000020异常代码: 0x0000008badf00d高亮线程: 0 应用特定信息:com.myapps未能及时启动 已用CPU总时间(秒):4.420(用户4.420,系统0.000),10%CPU已用应用程序CPU时间(秒):0.714,2%CPU 线程0:0

  • spring-boot-starter-parent使用1.5.9 依赖关系: 应用: 错误: [12 Sep 2018 20:36:26,702][错误]org.springframework.boot.springapplication:应用程序启动失败java.lang.nosuchmethoder错误:org.springframework.boot.builder.springappli

  • 我对@Async和Rest模板调用有问题;下面是我的主要应用程序类,带有一个任务执行器Bean和EnableAsync注释 这是我在Rest控制器中调用的带有异步注释的my测试服务: 此服务在rest模板上返回一个nullPointer;这是stacktrace 但是如果我删除@enableAsync和@Async,那么简单的Rest模板可以很好地工作。 当我传递HttpServlet请求时,Ec

  • 我最初的程序是为了将数据插入我的数据库。我有4个表,其中插入了数据,为了优化起见,我在一个单独的线程中这样做,因为实体是异步创建的。我正在使用consume方法将实体添加到队列中。 过了一段时间,我决定使用Spring Boot将web api添加到我的应用程序中。Spring Data JPA是需要的,因为一些POST请求将数据插入到我的数据库中。但是Spring Data JPA与我已经在使用