SpringBoot - BeanDefinitionOverrideException:无效的 bean 定义

SpringBoot - BeanDefinitionOverrideException: Invalid bean definition

我正在尝试使用 Spring Boot 在本地设置 DynamoDB。最初我的设置工作正常,并且能够通过存储库 write/save 到 DynamoDB。从那时起,我添加了更多 类 来构建我的应用程序。现在,当我尝试启动我的应用程序时,出现以下异常:

org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'agentRepository' defined in null: Cannot register bean definition [Root bean: class [org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] for bean 'agentRepository': There is already [Root bean: class [org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound.

我广泛搜索了 SO 和互联网,但没有任何有用的解决方案。错误消息也具有误导性。

我的项目具有以下层次结构

ai.test.as
  - as
      - agent
          - business
          - intent
          - exception
          - Agent.java
          - AgentDTO.java
          - AgentRespository.java
          - AgentController.java
          - AgentService.java
          - AgentServiceImpl.java
  - config
     - DynamoDBConfig.java

DynamoDBConfig.java

package ai.test.as.config;

import ai.test.as.agent.AgentRepository;
import ai.test.as.agent.intent.template.TemplateRepository;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDynamoDBRepositories(basePackageClasses = {AgentRepository.class})
public class DynamoDBConfig
{
    @Value("${aws.dynamodb.endpoint}")
    private String dynamoDBEndpoint;

    @Value("${aws.auth.accesskey}")
    private String awsAccessKey;

    @Value("${aws.auth.secretkey}")
    private String awsSecretKey;

    @Bean
    public AmazonDynamoDB amazonDynamoDB()
    {
        AmazonDynamoDB dynamoDB = new AmazonDynamoDBClient(getAwsCredentials());
        dynamoDB.setEndpoint(dynamoDBEndpoint);

        return dynamoDB;
    }

    @Bean
    public AWSCredentials getAwsCredentials()
    {
        return new BasicAWSCredentials(awsAccessKey, awsSecretKey);
    }
}

AgentRepository.java

package ai.test.as.agent;

import ai.test.as.agent.Agent;
import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
import org.springframework.data.repository.CrudRepository;

@EnableScan
public interface AgentRepository extends CrudRepository<Agent, String>
{
}

AgentController.java(使用AgentRepository的地方)

@RestController
@RequestMapping(value = "/v1/agents")
public class AgentController
{
    @Autowired
    private AgentRepository agentRepository;

    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public void test()
    {
        Agent agent = new Agent();
        agent.setAgentNumber("123456");
        agent.setId(1);

        agentRepository.save(agent);
    }
}

Spring 建议如下: > The bean 'agentRepository', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.

这里的null是什么意思?是因为我的应用程序配置有问题吗?还有怎么可能已经注册了?

请给我一些指点,因为我对接下来的步骤很困惑。

从 Spring Boot 2.1 开始,必须启用 Bean 覆盖,

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.1-Release-Notes

Bean Overriding

Bean overriding has been disabled by default to prevent a bean being accidentally overridden. If you are relying on overriding, you will need to set spring.main.allow-bean-definition-overriding to true.

设置

spring.main.allow-bean-definition-overriding=true

或yml,

spring:
   main:
     allow-bean-definition-overriding: true

再次启用覆盖。

编辑,

Bean 覆盖基于 bean 的名称而不是其类型。例如

@Bean
public ClassA class(){
   return new ClassA();
}

@Bean
public ClassB class(){
   return new ClassB();
}

在> 2.1 中会导致这个错误,默认情况下bean 名称取自方法名称。重命名方法或将 name 属性添加到 Bean 注释将是一个有效的修复。

例如使用这种方法启用 bean 覆盖

@SpringBootTest(properties = "spring.main.allow-bean-definition-overriding=true")

@SpringBootApplication (properties = "spring.main.allow-bean-definition-overriding=true")

我想我和 MongoDB 有同样的问题。至少错误消息看起来完全一样,而且我也只有一个 MongoDB 的存储库,像这样:

public interface MyClassMongoRepository extends MongoRepository<MyClass, Long> {
}

问题是由 class MyClass 引起的,它曾在另一个数据库中使用过。 Spring 在创建 MongoRepository 之前默默地创建了一些 JpaRepository。两个存储库的名称相同,导致冲突。

解决方案是制作 MyClass 的副本,将其移动到 MongoRepository 的包中并删除任何特定于 JPA 的注释。

我在尝试通过 spring-data-jdbc 添加 PostgreSQL 数据库到已经使用 MongoDB 的现有项目时偶然发现了同样的问题。

问题似乎是 MongoDB 和 PostgreSQL 的存储库被两个模块扫描(spring-mongo 和 spring-jdbc).他们都试图创造一些豆子并发生冲突。

在我的例子中,MongoDB 存储库和 PostgreSQL 存储库在同一个包中。

接受的答案为我解决了问题 - 但我从这个启动日志中得到了一些提示:

Finished Spring Data repository scanning in 319ms. Found 4 repository interfaces
Finished Spring Data repository scanning in 319ms. Found 5 repository interfaces

这很奇怪,因为我只有 1 个 PostgreSQL 存储库和 4 个 MongoDB。

我将 PostgreSQL 存储库移动到与 MongoDB 存储库不同的包中,并将 PostgreSQL 存储库的基础包配置到新包中。 就我而言:

@EnableJdbcRepositories(basePackageClasses = MyOnlyPostgreSQLRepository.class) // TODO: Use the real package or a dedicated base class

这为我解决了这个问题(没有 属性 设置 bean 覆盖 - 我更喜欢)。启动日志现在还显示正确数量的存储库(1 和 4)。

在我的例子中,2 个 Maven 依赖项是用同一个 Bean 定义的。 我在为我的所有项目发布 mvn dependency:tree 时发现了这一点。

我遇到了同样的问题,问题是多个存储库工厂试图向它们注册所有存储库接口。就我而言,它是 JpaRepositoryFactoryBean & DynamoDBRepositoryFactoryBean。正如其他答案中提到的,您可以在以下指示的日志中看到:

[INFO] Bootstrapping Spring Data DynamoDB repositories in DEFAULT mode.
[INFO] Finished Spring Data repository scanning in 64ms. Found 2 DynamoDB repository interfaces.
[INFO] Bootstrapping Spring Data JPA repositories in DEFAULT mode.

解决方法是:

  1. 通过检查 compatibility matrix[=25=,确保您使用的是 spring-data-dynamodb / spring-boot / spring-data 的兼容版本]
  2. 确保每个存储库只创建一次。就我而言,我必须添加
@SpringBootApplication
@EnableAutoConfiguration(exclude = {
       DataSourceAutoConfiguration.class,
       DataSourceTransactionManagerAutoConfiguration.class,
       HibernateJpaAutoConfiguration.class})

不同版本的配置可能不同,具体取决于您的应用程序中有多少存储库。阅读 Multi-Repository-configuration

可能会有帮助