2016-08-19 2 views
0

для текущего проекта я хотел бы иметь такую ​​возможность:Создать различные бобы динамически

«Для любого интерфейса расширения интерфейса X, создать компонент с помощью статического фабричного метода, с помощью другого (autowired) боба».

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

В настоящее время я пытаюсь сделать это с помощью простого боба ...

@Component 
public class DynamicBeanFactory { 

    @Autowired 
    private Service myService; 

    @Autowired 
    private ConfigurableListableBeanFactory beanFactory; 

    protected List<Class<? extends X>> findAllSubclasses() { ... } 

    @PostConstruct 
    public void createOneBeanPerClass() { 
     ... create beans from findAllSubclasses(), using myService 
     beanFactory.registerSingleton(name, bean); 
    } 
} 

Очевидно, что это приводит к проблеме, так как, к примеру ...

@Autowired 
private YextendingX dependency; 

... не работает все время, так как Spring не знает, что YextendingX будет доступен только после создания DynamicBeanFactory, что приводит к необходимости использования @DependsOn("dynamicBeanFactory"), чтобы быть уверенным.

Итак, есть ли лучший способ вставить бит (определение) в жизненный цикл, так что какой-то заводский класс используется для создания нескольких компонентов (определений), с возможностью использования @Autowired.

ответ

0

После игры вокруг некоторое время, следующие решения, кажется, сделать трюк ...

@Component 
public class DynamicBeanRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { 

    @Override 
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { 

     List<Class<? extends X> classes = findAllSubclasses(); // implemented via Reflections 

     for (Class<? extends X> clz : classes) { 

      RootBeanDefinition beanDefinition = new RootBeanDefinition(clz); 
      beanDefinition.setTargetType(clz); 
      beanDefinition.setFactoryBeanName("myFactoryBean"); 
      beanDefinition.setFactoryMethodName("myFactoryMethod"); 

      ConstructorArgumentValues properties = new ConstructorArgumentValues(); 
      properties.addGenericArgumentValue("someString"); 
      properties.addGenericArgumentValue(clz);    
      beanDefinition.setConstructorArgumentValues(properties); 

      beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); 
      beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON); 
      registry.registerBeanDefinition(entry.getKey(), beanDefinition); 
     } 

    } 
etc. 

Таким образом, все бобы, кажется, нашли и добавили в бинов, поэтому порядок их создания может быть определяется правильно. Для их создания метод myFactoryMethod вызывается на компоненте myFactoryBean с использованием двух параметров "someString" и classclz желаемого компонента.

Смежные вопросы