为什么 Spring Boot 找不到尝试执行自动装配的 @Service bean? bean 存在但找不到
Why Spring Boot is not finding a @Service bean trying to perform autowiring? the bean exist but it can't find it
我在使用 Spring Boot 2.2.5.RELEASE 项目时遇到一个奇怪的问题,该项目使用 JUnit.
我尝试详细解释我的问题:
1) 我定义了一个服务。首先我定义了一个名为OrderService的接口,像这样:
package com.dgs.soc.service;
import java.util.List;
import com.dgs.soc.excelapi.dto.Order;
public interface OrderService {
public List<Order> getOrdersList();
}
然后我定义了它的实现,目前非常简单,名为 OrderServiceImpl:
package com.dgs.soc.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.dgs.soc.excelapi.dto.Order;
import com.dgs.soc.repository.OrderRepository;
@Service
public class OrderServiceImpl {
public List<Order> getOrdersList() {
List<Order> result = new ArrayList<Order>();
return result;
}
}
如您所见,此 class 由 @Service 注释注释。
问题是使用 JUnit,我有这个测试 class:
package com.dgs.soc.excelapi.integration;
// IMPORTS LIST
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { Application.class })
@WebAppConfiguration
@ActiveProfiles(profiles = { "no-liquibase" })
public class ExcelResourceIntegrationTest {
@Autowired
OrderServiceImpl orderService;
@Test
public void getOrdersListRepositoryTest() {
List<Order> ordersList = orderService.getOrdersList();
assertThat(ordersList).isNotEmpty();
}
}
我遇到了一个奇怪的行为:执行 getOrdersListRepositoryTest() 测试方法我得到了这个异常
2020-03-23 04:42:24.783 ERROR 5281 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@7fbdb894] to prepare test instance [com.dgs.soc.excelapi.integration.ExcelResourceIntegrationTest@2ad6895a]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.dgs.soc.excelapi.integration.ExcelResourceIntegrationTest': Unsatisfied dependency expressed through field 'orderService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.dgs.soc.service.OrderServiceImpl' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:393) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43) ~[spring-boot-test-autoconfigure-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runReflectiveCall(SpringJUnit4ClassRunner.java:289) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:290) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) ~[junit-4.12.jar:4.12]
at org.junit.runner.JUnitCore.run(JUnitCore.java:115) ~[junit-4.12.jar:4.12]
at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40) ~[junit-vintage-engine-5.5.2.jar:5.5.2]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) ~[na:na]
at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80) ~[junit-vintage-engine-5.5.2.jar:5.5.2]
at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:71) ~[junit-vintage-engine-5.5.2.jar:5.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute(DefaultLauncher.java:197) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210) ~[.cp/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.dgs.soc.service.OrderServiceImpl' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1695) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1253) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
... 49 common frames omitted
2020-03-23 04:42:24.816 INFO 5281 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
2020-03-23 04:42:24.819 INFO 5281 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-03-23 04:42:24.846 INFO 5281 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-03-23 04:42:24.875 INFO 5281 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
它说 没有可用的 'com.dgs.soc.service.OrderServiceImpl' 类型的合格 bean 但是,正如您在前面的代码中看到的那样,这个 bean 存在并且由 [= 注释57=]@Service 允许自动装配的注解!!!
在该项目中定义了一个 class,由 @RestController 注释,公开了 API。如果进入这个 class 我尝试自动装配相同的服务 class,像这样:
@Description(value = "Resource layer for handling REST requests.")
@RestController
@RequestMapping("api")
public class ExcelResource {
@Autowired
OrderServiceImpl orderService;
.......................................................
.......................................................
.......................................................
}
现在我尝试将应用程序作为 Spring 启动应用程序 我遇到了同样的问题:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field orderService in com.dgs.soc.excelapi.resources.ExcelResource required a bean of type 'com.dgs.soc.service.OrderServiceImpl' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.dgs.soc.service.OrderServiceImpl' in your configuration.
但是 com.dgs.soc.service.OrderServiceImpl bean 再次存在并且由 @Service.
注释
为什么我会遇到这个问题?我错过了什么?我该如何解决这个问题?我在想我有一些参考问题或类似的问题,但我不知道
编辑-1:
将 @ComponentScan("com.dgs.soc.service") 放在我的 Application class 的拓扑上,它似乎可以工作,但我有一些疑惑!!!
所以这是我的申请class现在:
package com.dgs.soc.excelapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan("com.dgs.soc.service")
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
它可以工作,但我认为它应该在没有 ** @ComponentScan("com.dgs.soc.service")** 注释的情况下也可以工作,因为这个 class 被 @[=112= 注释了]BootApplication 你可以在这里读到:
自动启用@ComponentScan:对应用程序所在的包进行@Component扫描(参见最佳实践)
所以应用程序位于 com.dgs.soc.excelapi 中,理论上我预计组件扫描也必须在没有明确定义 的情况下正常工作@ComponentScan
为什么?有什么想法吗?
尝试将 @ComponentScan
注释放在主应用程序之上 class
@ComponentScan("base.package.name")
问题如下:
您的应用程序 class 在程序包 "com.dgs.soc.excelapi"
中
@SpringBootApplication 扫描该包及其所有子包 @Services/@Components/@Repositories。
虽然您将所有服务放在完全不同的包中 ("com.dgs.soc.service"),因此 Spring 引导程序找不到它们。因此 @ComponentScan 注释有效。
修复:重新排序您的包结构。
你的问题的答案是你没有合适的包结构 spring-boot auto scan 来获取你的服务 class。
SpringBootApplication
注释仅启用扫描它所在的包及其子包。
如果 com.acme.app
包中有 SpringBootApplication
class 那么所有带有 spring 引导注释的 class 都会在包中被扫描 com.acme.app
及其任何子包,即 com.acme.app.services
、com.acme.app.controllers
等。但是,如果您有一个包 com.acme.services
,则不会从中自动扫描任何 spring 注释包裹。
您有两个选择;
您要么修改包结构以允许 spring-boot 自动扫描所有注释。在您的情况下,将 Application
class 从 com.dgs.soc.excelapi
移动到 com.dgs.soc
。或者您可以移动所有其他包,即 com.dgs.soc.excelapi
.
下的服务
您使用 @ComponentScan 或 SpringBootApplication
注释上的 scanBasePackages
属性明确列出要扫描的包。
我在使用 Spring Boot 2.2.5.RELEASE 项目时遇到一个奇怪的问题,该项目使用 JUnit.
我尝试详细解释我的问题:
1) 我定义了一个服务。首先我定义了一个名为OrderService的接口,像这样:
package com.dgs.soc.service;
import java.util.List;
import com.dgs.soc.excelapi.dto.Order;
public interface OrderService {
public List<Order> getOrdersList();
}
然后我定义了它的实现,目前非常简单,名为 OrderServiceImpl:
package com.dgs.soc.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.dgs.soc.excelapi.dto.Order;
import com.dgs.soc.repository.OrderRepository;
@Service
public class OrderServiceImpl {
public List<Order> getOrdersList() {
List<Order> result = new ArrayList<Order>();
return result;
}
}
如您所见,此 class 由 @Service 注释注释。
问题是使用 JUnit,我有这个测试 class:
package com.dgs.soc.excelapi.integration;
// IMPORTS LIST
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { Application.class })
@WebAppConfiguration
@ActiveProfiles(profiles = { "no-liquibase" })
public class ExcelResourceIntegrationTest {
@Autowired
OrderServiceImpl orderService;
@Test
public void getOrdersListRepositoryTest() {
List<Order> ordersList = orderService.getOrdersList();
assertThat(ordersList).isNotEmpty();
}
}
我遇到了一个奇怪的行为:执行 getOrdersListRepositoryTest() 测试方法我得到了这个异常
2020-03-23 04:42:24.783 ERROR 5281 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@7fbdb894] to prepare test instance [com.dgs.soc.excelapi.integration.ExcelResourceIntegrationTest@2ad6895a]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.dgs.soc.excelapi.integration.ExcelResourceIntegrationTest': Unsatisfied dependency expressed through field 'orderService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.dgs.soc.service.OrderServiceImpl' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:393) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43) ~[spring-boot-test-autoconfigure-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runReflectiveCall(SpringJUnit4ClassRunner.java:289) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:290) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) ~[spring-test-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) ~[junit-4.12.jar:4.12]
at org.junit.runner.JUnitCore.run(JUnitCore.java:115) ~[junit-4.12.jar:4.12]
at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40) ~[junit-vintage-engine-5.5.2.jar:5.5.2]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) ~[na:na]
at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80) ~[junit-vintage-engine-5.5.2.jar:5.5.2]
at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:71) ~[junit-vintage-engine-5.5.2.jar:5.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute(DefaultLauncher.java:197) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137) ~[junit-platform-launcher-1.5.2.jar:1.5.2]
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210) ~[.cp/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.dgs.soc.service.OrderServiceImpl' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1695) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1253) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
... 49 common frames omitted
2020-03-23 04:42:24.816 INFO 5281 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
2020-03-23 04:42:24.819 INFO 5281 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-03-23 04:42:24.846 INFO 5281 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-03-23 04:42:24.875 INFO 5281 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
它说 没有可用的 'com.dgs.soc.service.OrderServiceImpl' 类型的合格 bean 但是,正如您在前面的代码中看到的那样,这个 bean 存在并且由 [= 注释57=]@Service 允许自动装配的注解!!!
在该项目中定义了一个 class,由 @RestController 注释,公开了 API。如果进入这个 class 我尝试自动装配相同的服务 class,像这样:
@Description(value = "Resource layer for handling REST requests.")
@RestController
@RequestMapping("api")
public class ExcelResource {
@Autowired
OrderServiceImpl orderService;
.......................................................
.......................................................
.......................................................
}
现在我尝试将应用程序作为 Spring 启动应用程序 我遇到了同样的问题:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field orderService in com.dgs.soc.excelapi.resources.ExcelResource required a bean of type 'com.dgs.soc.service.OrderServiceImpl' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.dgs.soc.service.OrderServiceImpl' in your configuration.
但是 com.dgs.soc.service.OrderServiceImpl bean 再次存在并且由 @Service.
注释为什么我会遇到这个问题?我错过了什么?我该如何解决这个问题?我在想我有一些参考问题或类似的问题,但我不知道
编辑-1: 将 @ComponentScan("com.dgs.soc.service") 放在我的 Application class 的拓扑上,它似乎可以工作,但我有一些疑惑!!!
所以这是我的申请class现在:
package com.dgs.soc.excelapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan("com.dgs.soc.service")
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
它可以工作,但我认为它应该在没有 ** @ComponentScan("com.dgs.soc.service")** 注释的情况下也可以工作,因为这个 class 被 @[=112= 注释了]BootApplication 你可以在这里读到:
自动启用@ComponentScan:对应用程序所在的包进行@Component扫描(参见最佳实践)
所以应用程序位于 com.dgs.soc.excelapi 中,理论上我预计组件扫描也必须在没有明确定义 的情况下正常工作@ComponentScan
为什么?有什么想法吗?
尝试将 @ComponentScan
注释放在主应用程序之上 class
@ComponentScan("base.package.name")
问题如下:
您的应用程序 class 在程序包 "com.dgs.soc.excelapi"
中@SpringBootApplication 扫描该包及其所有子包 @Services/@Components/@Repositories。
虽然您将所有服务放在完全不同的包中 ("com.dgs.soc.service"),因此 Spring 引导程序找不到它们。因此 @ComponentScan 注释有效。
修复:重新排序您的包结构。
你的问题的答案是你没有合适的包结构 spring-boot auto scan 来获取你的服务 class。
SpringBootApplication
注释仅启用扫描它所在的包及其子包。
如果 com.acme.app
包中有 SpringBootApplication
class 那么所有带有 spring 引导注释的 class 都会在包中被扫描 com.acme.app
及其任何子包,即 com.acme.app.services
、com.acme.app.controllers
等。但是,如果您有一个包 com.acme.services
,则不会从中自动扫描任何 spring 注释包裹。
您有两个选择;
您要么修改包结构以允许 spring-boot 自动扫描所有注释。在您的情况下,将
Application
class 从com.dgs.soc.excelapi
移动到com.dgs.soc
。或者您可以移动所有其他包,即com.dgs.soc.excelapi
. 下的服务
您使用 @ComponentScan 或
SpringBootApplication
注释上的scanBasePackages
属性明确列出要扫描的包。