Программно имитировать метод @Bean для регистрации нескольких экземпляров в виде bean-компонентов - PullRequest
0 голосов
/ 13 июня 2018

(пружинный ботинок 1.5, Java 8)

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

Этот класс конфигурации внедряет Foundation и создает бобы стены, так что в потолки могут быть введены стены.Не обращайте внимания на плохие практики, я просто стараюсь сделать код как можно более коротким, не меняя основных механизмов.

@Configuration
class Config {
  @Autowired
  Foundation foundation;

  @Bean
  // assume there is a lot of repetitive logic here
  WoodenWall wood() { return new WoodenWall(foundation); }

  @Bean
  BrickWall brick() { return new BrickWall(foundation); }
}

И потолок:

@Component
class KitchenCeiling {
  @Autowired
  WoodWall wall;
}

Я собираюсь сделать намного больше типов Стен и хочу, чтобы они все были зарегистрированы как бобы.Вместо того, чтобы определять метод @Bean для каждого из них, я хочу создать их все в цикле и зарегистрировать их вручную за один раз.Подумайте о AllTypesOfWallsBeanFactory, если хотите.

@Configuration
class Config implements ??? {
  @Autowired
  Foundation foundation;

  @Override
  void addBeans(??? beanRegistry) {
    for (Class beanClass : wallClasses) {
      // instantiate BrickWall, WoodWall, etc
      registry.add(beanClass.getSimpleName(), beanClass, wallInstance);
    }
  }
}

Проблема в том, что я не могу найти подходящий интерфейс для реализации или правильный SpringBeanRegistryPostProcessorFactoryImplementationThingamajig, чтобы перейти к.Я пробовал ответы на все другие сообщения SO, которые мог найти, но ни один из них не делает правильных действий.


Одна из проблем здесь заключается в том, что мне нужен контекст, чтобы уже инициализировать bean-компоненты, так как мне нуженFoundation, но я также хочу добавить еще несколько bean-компонентов в контекст, чтобы Ceilings, которые еще должны быть инициализированы, могли внедрить мои свежеприготовленные Walls.

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

Я знаю, что разрешить зависимость сложнее в этой ситуации (поскольку у Spring нет отражающей информации, чтобы вычислить общий следующий порядок), но это должно бытьможно сказать пружине

  1. инициализировать, какие у него есть зависимости для
  2. обработки вновь созданных bean-компонентов
  3. goto 1

BeanDefinition не вписывается в счет, потому что не требует каких-либо примеров, и чтобы использовать настройку factoryMethod, мне нужно было бы создать класс фабрики для каждой стены.Возвращаемся к исходной точке.

Большинство интерфейсов BeanDefinitionRegistryPostProcessor и др. Вызываются слишком поздно, не вводите бины, которые я даю им, в зависимые бины (был 1, который занял экземпляров но ничего с ними не делал), или требует конструктор по умолчанию (т.е. без зависимостей).Они также имеют тенденцию давать вам объекты, которые берут только BeanDefinition.

В другом проекте, где была аналогичная потребность, в конечном итоге использовался фабричный метод с еще методом @Bean для каждого его экземпляра.необходимо произвести.Я начинаю думать, что на самом деле это невозможно, и то, что было сделано в этом проекте, настолько хорошо, насколько это возможно.

Ответы [ 2 ]

0 голосов
/ 14 июня 2018

Я собираюсь заключить, что просто невозможно сделать это надежно.Лучшее, что можно сделать, - это создать фабричный метод и метод @Bean, вызывающий фабрику для каждого экземпляра бина, который должен быть зарегистрирован.Кажется невозможным вырезать @Bean методы из картинки.

0 голосов
/ 13 июня 2018

Вы можете попробовать использовать @PostConstruct с ConfigurableApplicationContext

@Configuration
class Config {

  @Autowired
  Foundation foundation;

  @Autowired
  ConfigurableApplicationContext ctx;

  @PostConstruct
  void addBeans() {
    for (Class beanClass : wallClasses) {
      ctx.getBeanFactory().registerSingleton(beanClass.getSimpleName(), beanClass, wallInstance);
    }
  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...