为什么我的依赖项Spring bean实例化了两次?一次来自jar依赖项,一次来自classpath

时间:2018-12-09 17:46:19

标签: java spring spring-boot

我有史以来最令人困惑的Spring错误消息,好几年来,我都收到了一些,但这是一个值得记住的消息。

错误消息是:

void qux() {
  foo(3);
}

Field orderService in com.thalasoft.butik.rest.config.FixtureService required a single bean, but 2 were found: - com.thalasoft.butik.data.service.OrderServiceImpl: defined in URL [jar:file:/home/stephane/.m2/repository/com/thalasoft/butik-data/0.0.1-SNAPSHOT/butik-data-0.0.1-SNAPSHOT.jar!/com/thalasoft/butik/data/service/OrderServiceImpl.class] - OrderService: defined by method 'OrderService' in class path resource [com/thalasoft/butik/data/config/JpaService.class] 应用程序由2个Spring项目组成,一个是butik项目,另一个是butik-data项目。

butik-rest项目中运行集成测试时发生错误

butik-rest

运行应用程序而不运行集成测试时,会发生非常相同的错误:

mvn clean install -Denv="test" -Ddb="h2"

该依赖性仅在mvn clean spring-boot:run 文件中存在一次:

pom.xml

我的<dependency> <groupId>com.thalasoft</groupId> <artifactId>butik-data</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> 项目配置如下:

butik-rest

集成测试配置:

@EnvProd
@SpringBootApplication
@Slf4j
public class Application implements CommandLineRunner {

@Component
@ComponentScan(nameGenerator = PackageBeanNameGenerator.class, basePackages = { "com.thalasoft.butik.rest.service", "com.thalasoft.butik.data" })
public class ApplicationConfiguration {
}

@Component
@EnableWebMvc
@EnableSpringDataWebSupport
@ComponentScan(nameGenerator = PackageBeanNameGenerator.class, basePackages = { "com.thalasoft.butik.rest.exception",
    "com.thalasoft.butik.rest.controller", "com.thalasoft.butik.rest.assembler" })
public class WebConfiguration implements WebMvcConfigurer {

在依赖项项目中显式实例化了服务bean:

@RunWith(SpringRunner.class)
@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = {
    "classpath:mysql/clean-up-before-each-test.sql" })
public abstract class BaseTest {

@Configuration
@EnableAutoConfiguration
@ComponentScan(nameGenerator = PackageBeanNameGenerator.class, basePackages = { "com.thalasoft.butik.rest.config",
    "com.thalasoft.butik.rest.service", "com.thalasoft.butik.data" })
public class TestConfiguration {
}

@EnableWebSecurity
@ComponentScan(nameGenerator = PackageBeanNameGenerator.class, basePackages = { "com.thalasoft.butik.rest.filter" })
public class NoSecurityConfiguration extends WebSecurityConfigurerAdapter {

是不是Spring从@Configuration public class JpaService { @Bean public ProductServiceImpl ProductService() { return new ProductServiceImpl(); } @Bean public OrderServiceImpl OrderService() { return new OrderServiceImpl(); } } 项目中的上述显式实例中获得了一个bean,而又从butik-data依赖项目中的"com.thalasoft.butik.data"扫描中获得了另一个bean?

更新:即使将butik-rest的两个实例(有一个实例用于运行应用程序,另一个实例用于运行集成测试)更改为"com.thalasoft.butik.data",我仍然遇到相同的错误。

更新:我看到我有2个错误使整个问题变得有些棘手。我还必须从集成测试中删除"com.thalasoft.butik.data.config"实例。现在问题解决了。

1 个答案:

答案 0 :(得分:1)

您似乎已经扫描了这两个位置。您需要调查当前正在扫描以及应该扫描的地方。

如果您认为当前的扫描方式(包括两个适合自动装配'orderService'字段的bean),则可以通过注释 @Primary (docs:{{ 3}})。

使用此注释标记的Bean优于其他注释,这应该可以解决您的问题。

祝你好运:)