动态创建各种bean

时间:2016-08-19 10:53:07

标签: spring dependency-injection spring-bean

对于当前项目,我希望具备以下功能:

“对于扩展接口X的任何接口,使用另一个(自动装配的)bean通过此静态工厂方法创建一个bean。”

查找扩展X的所有接口都没有问题,反射做得非常好。但我还没有找到任何方法将自己注入Spring生命周期,以便Springs知道这些bean可以存在。

目前,我正在尝试使用简单的bean ...

@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后才可用,这导致需要{ {1}},只是为了确定。

那么,有没有更好的方法将Bean(定义)注入生命周期,因此一些工厂类用于创建许多bean(定义),并且能够在那里使用@DependsOn("dynamicBeanFactory")

1 个答案:

答案 0 :(得分: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.

这样,所有bean似乎都找到并添加为bean定义,因此可以正确地确定它们的创建顺序。为了创建它们,使用所需bean的两个参数myFactoryMethodmyFactoryBean "someString"在bean class上调用方法clz