Java SpringBoot - BeanDefinitionOverrideException:无效的 bean 定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/53723303/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:53:14  来源:igfitidea点击:

SpringBoot - BeanDefinitionOverrideException: Invalid bean definition

javaspringspring-bootamazon-dynamodbspring-bean

提问by Vino

I am trying to setup DynamoDB locally with Spring Boot. Initially I got the setup working and was able to write/save to DynamoDB via a repository. From that point I added more classes to build my application. Now when I try to start my application, I get the following exception:

我正在尝试使用 Spring Boot 在本地设置 DynamoDB。最初,我使设置正常工作,并且能够通过存储库写入/保存到 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.

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.

I have searched SO and internet extensively but there were no any useful solution to this. The error message is misleading as well.

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

My project is of the following hierarchy

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

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

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

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 (Where AgentRepository is used)

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 suggests the following: > 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.

春天提出以下建议: > 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

What does nullmean here? Is it because something wrong in my application config? Also how is it possible that it is already registered?

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

Please give me some pointers because I so confused about my next steps.

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

采纳答案by Darren Forsythe

Bean overriding has to be enabled since Spring Boot 2.1,

自 Spring Boot 2.1 起必须启用 Bean 覆盖,

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

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.

Bean覆盖

默认情况下已禁用 Bean 覆盖,以防止 Bean 被意外覆盖。如果您依赖覆盖,则需要将 spring.main.allow-bean-definition-overriding 设置为 true。

Set

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

or yml,

或yml,

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

to enable overriding again.

再次启用覆盖。

Edit,

编辑,

Bean Overriding is based of the name of the bean not its type. e.g.

Bean Overriding 是基于 bean 的名称而不是它的类型。例如

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

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

Will cause this error in > 2.1, by default bean names are taken from the method name. Renaming the method or adding the nameattribute to the Beanannotation will be a valid fix.

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

回答by Shell Scott

Enable bean overriding with such approach for example

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

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

or

或者

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

回答by Sascha Doerdelmann

I think I had the same problem with MongoDB. At least the error message looked exactly the same and I also had just one repository for the MongoDB, something like this:

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

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

The problem had been caused by class MyClass which had been used in another database before. Spring silently created some JpaRepository before creating the MongoRepository. Both repositories had the same name which caused the conflict.

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

Solution was to make a copy of MyClass, move it into the package of the MongoRepository and remove any JPA-specific annotations.

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