SpringBoot-BeanDefinition itionOverrideException: bean 定义无效

我正在尝试用 SpringBoot 在本地设置 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.

我已经搜索了所以和互联网广泛,但没有任何有用的解决方案。错误消息也会引起误解。

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

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

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);
}
}

代理 Repository.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>
{
}

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);
}
}

斯普林提出了以下建议: > 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在这里是什么意思?是因为我的应用程序配置有问题吗?还有,它怎么可能已经注册了?

请给我一些建议,因为我对我的下一步感到困惑。

121092 次浏览

Bean overriding has to be enabled since Spring Boot 2.1,

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.

Set

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

or 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
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 name attribute to the Bean annotation will be a valid fix.

Enable bean overriding with such approach for example

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

or

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

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:

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.

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

I just stumbled across the same issue while trying to add a PostgreSQL database via spring-data-jdbc to an existing project wich was already using a MongoDB.

It seems like the problem was that the repositories for MongoDB and PostgreSQL were scanned by both modules (spring-mongo and spring-jdbc). They both try to create some beans and clash.

In my case the MongoDB repositories and the PostgreSQL repositories were in the same package.

The accepted answer solved the problem for me - but i kind of got a hint from this startup logs:

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

This is weird because i only have 1 repository for PostgreSQL and 4 for MongoDB.

I moved the PostgreSQL repository into a different package than the MongoDB repository and configured the base package of the PostgreSQL repositories to the new package. In my case:

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

This solved the issue for me (no property set for bean overriding - which i prefer). The startups logs also show the correct amount of repositories now (1 and 4).

In my case was that 2 maven depenencies were defined with the same Bean in it. I found this when issuing a mvn dependency:tree for all my projects.

I came across this same issue, the problem was that multiple repository factories were trying to register all repositories interfaces with them. In my case, it was JpaRepositoryFactoryBean & DynamoDBRepositoryFactoryBean. As mentioned in other answers, you could see that on the logs indicated by:

[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.

Solution is:

  1. Make sure you are using compatible versions of spring-data-dynamodb / spring-boot / spring-data by checking the compatibility matrix
  2. Make sure each repository is created only once. In my case, I had to add
@SpringBootApplication
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class})

The config may differ in different versions and depending on how many repositories you have in your application. It may be helpful to read about Multi-Repository-configuration

you can use spring.main.allow-bean-definition-overriding=true in application.properties file

or

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