我在简单的Spring Boot应用程序上工作,并希望在其上使用并发线程。为了实现这一点,我在服务方法上使用了@Async注释,但是当我添加@Async注释时,Spring DI崩溃了。它在没有问题的情况下在没有@Async的情况下工作。要调用服务方法,我创建jUnit测试。错误日志显示DI不起作用,并且没有为服务类找到此类bean。请帮助在Spring上使用@Async运行多个线程。
修改 我尝试在我的测试类@Autowired服务接口而不是它的实现中放入,之后@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
答案 0 :(得分:1)
类basePackages
上@ComponentScan
注释的CLApplication
属性错误:
@ComponentScan(basePackages = {"org.cl, org.cl.service.location "})
这应该是:
@ComponentScan(basePackages = {"org.cl", "org.cl.service.location"})
这两个包应该指定为两个单独的字符串,而不是一个字符串,其中包名用逗号分隔。
您也可以指定org.cl
,因为Spring也会查看所有子包,因此如果您指定org.cl.service.location
,也会扫描org.cl
:
@ComponentScan(basePackages = "org.cl")
事实上,由于它是一个Spring Boot应用程序,您可以完全删除@ComponentScan
注释,因为@SpringBootApplication
注释已经自动包含它(它将扫描包和类{{{}的所有子包1}}在。)。
答案 1 :(得分:1)
您的应用程序崩溃是因为您在同一类中使用了异步方法(processPage())。 请检查-https://dzone.com/articles/effective-advice-on-spring-async-part-1
在您的应用程序中使用@Async的规则很少:
答案 2 :(得分:0)
只需将@Configuration添加到您的服务类
@Configuration
@Service
public class CatalogPageServiceImpl implements CatalogPageService