SpringBoot - BeanDefinitionOverrideException: недопустимое определение bean-компонента

Я пытаюсь настроить DynamoDB локально с помощью Spring Boot. Первоначально я получил настройку и смог записывать / сохранять в 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? Это потому, что что-то не так в конфигурации моего приложения? Также как это возможно, что он уже зарегистрирован?

Пожалуйста, дайте мне несколько советов, потому что я так запутался в своих следующих шагах.

Вы пробовали аннотировать AgentRepository с помощью @Component?

OEH 11.12.2018 12:36

Раньше, когда я пытался, я не использовал аннотацию @Component для чтения и записи из DynamoDB. Но, тем не менее, я попробовал сейчас, как вы упомянули, и это не сработало.

Vino 11.12.2018 12:39

Что касается вашего вопроса, если компонент уже зарегистрирован, вы можете распечатать весь компонент в контексте с помощью метода getBeanDefinitionNames () объекта ApplicationContext. Распечатав их в консоли, вы можете увидеть, какие ключи beans используются. В сети есть несколько примеров, поэтому я не буду им здесь делиться

OEH 11.12.2018 12:50

Не могли бы вы добавить аннотации [@Repository] или [@Service] в свой класс AgentRepository и попробовать? а также ваш AgentRepository - это интерфейс, есть ли какой-либо вариант использования интерфейса вместо классов.

venkat 11.12.2018 12:54

Привет, ты решил это? Я столкнулся с той же проблемой!

kkesley 19.08.2019 02:43

На самом деле нет, потому что я отказался от DynamoDB. При переключении БД проблема исчезла. Но хакерский способ исправить это - добавить spring.main.allow-bean-definition-overriding=true, как упоминалось в ответах.

Vino 19.08.2019 03:55

К сожалению, любой другой ответ касается того факта, что Зачем эта проблема начинает происходить. Теоретически лучшее разрешение могло бы начать определение того, почему и как у вас есть два боба.

Dherik 10.02.2020 14:11
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
77
7
91 503
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Переопределение bean-компонентов должно быть включено начиная с 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.

Набор

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-компонент? Я уверен, что создаю только один компонент AgentRepository. Так что отменяется?

Vino 11.12.2018 13:02

Прочтите это исключение, которое является нет, чему оно соответствует. Жалуется на bean-компонент DynamoDBRepositoryFactoryBean. Я предполагаю, что он уже регистрируется через загрузочное приложение, и @EnableDynamoDBRepositories(basePackageClasses = {AgentRepository.class}) не требуется. Также для того, кто проголосовал против этого, объяснять, почему.

Darren Forsythe 11.12.2018 13:04

Мнение, что это грязно, учитывая, что это функция в Spring Framework и широко используется. Удаление EnableDynamoDBRepositories(basePackageClasses = {AgentRepository.class}), я решаю эту проблему, но у меня нет доступа к настройке Dynamo, если бы я предполагал, что она может снова запускать создание bean-компонента, но если это не решит, я бы поднял проблему и предоставил пример .

Darren Forsythe 11.12.2018 13:13

@DarrenForsythe FYI Я попытался удалить @EnableDynamoDBRepositories и также удалил свойство переопределения, но проблема все еще сохраняется. Так что я думаю, что указанная аннотация нужна в любом случае.

Vino 11.12.2018 13:36

Я предполагаю, что это сторонняя библиотека, учитывая пакет, я бы обратился к сопровождающим с быстрым примером. Скорее всего, полагался на главные возможности

Darren Forsythe 11.12.2018 13:42

@DarrenForsythe Forsythe, как сообщить Spring использовать указанную вами конфигурацию, например yaml

Shell Scott 06.02.2020 15:22

@ShellScott, который зависит от того, используете вы application.yml или нет. Документация по конфигурации Spring Externalized может объяснить множество способов передачи параметров конфигурации.

Darren Forsythe 08.02.2020 00:31

Я считаю, что это очень рискованный обходной путь, который может привести к недетерминированному поведению. Лучше решить основную проблему, заключающуюся в том, что Spring пытается создать эти репозитории дважды. Скорее всего, вызвано неправильной конфигурацией или несовместимыми версиями spring-data-Dynamodb / spring-boot / spring-data

Ahmad Abdelghany 24.06.2021 11:01

Включите переопределение bean-компонентов с помощью такого подхода, например

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

или

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

Обратите внимание, что если это тестовый компонент, ваше решение практически такое же, не полагайтесь на именование bean-компонентов. переименуйте его, используйте первичный, если требуется, чтобы ввести его

Darren Forsythe 08.02.2020 00:30

Вы можете объяснить, почему это было необходимо?

Luan Torres 27.05.2021 14:47

Думаю, у меня была такая же проблема с MongoDB. По крайней мере, сообщение об ошибке выглядело точно так же, и у меня также был только один репозиторий для MongoDB, примерно так:

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

Проблема была вызвана классом MyClass, который раньше использовался в другой базе данных. Spring незаметно создал JpaRepository перед созданием MongoRepository. Оба репозитория имели одно и то же имя, что привело к конфликту.

Решением было сделать копию MyClass, переместить ее в пакет MongoRepository и удалить все аннотации, специфичные для JPA.

Да, это решает проблему, но связывает ваш код с поставщиком постоянства (MongoDB), что противоречит цели JPA.

Ahmad Abdelghany 24.06.2021 11:26

@AhmadAbdelghany, я знаю об этом, но я просто хотел предоставить другой вариант для разработчиков, которые не хотят изменять глобальный параметр, чтобы исправить все локальные проблемы.

Sascha Doerdelmann 29.06.2021 13:10

Я только что наткнулся на ту же проблему, пытаясь добавить базу данных PostgreSQL через spring-data-jdbc в существующий проект, который уже использовал 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).

да, я могу подтвердить, что добавление дополнительного bean-объекта @Configuration с @EnableJpaRepositories (basePackages = {"A.repository", "A.common.repository"}) решило проблему в моем случае (у меня были объекты репозитория, определенные как в моем основной проект (пакет A.repository) и в промежуточной библиотеке, на которую ссылается этот проект (пакет A.common.repository))

hello_earth 01.08.2021 14:47

В моем случае было то, что 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. Убедитесь, что вы используете совместимые версии spring-data-Dynamodb / spring-boot / spring-data, проверив матрица совместимости
  2. Убедитесь, что каждый репозиторий создается только один раз. В моем случае мне пришлось добавить
@SpringBootApplication
@EnableAutoConfiguration(exclude = {
       DataSourceAutoConfiguration.class,
       DataSourceTransactionManagerAutoConfiguration.class,
       HibernateJpaAutoConfiguration.class})

Конфигурация может отличаться в разных версиях и в зависимости от того, сколько репозиториев у вас в приложении. Может быть полезно прочитать о Конфигурация с несколькими репозиториями

Другие вопросы по теме