2011-05-26 80 views
15

如何创建一个由Spring使用具有@Configuration注释的类正确管理的bean集合。使用@Configuration在Spring中创建bean集合

我愿做这样的事情:

@Configuration 
public Config { 
    @Autowired 
    private SomeConfiguration config; 

    @Bean 
    public List<MyBean> myBeans() { 
     List<MyBean> beans = new ArrayList<MyBean>(); 
     for (Device device : config.getDevices()) { 
      beans.add(new MyBean(device)); 
     } 
     return beans; 
    } 
} 

但为myBean实例不后处理。所以他们的@Autowired方法没有被调用,bean没有被注册为mbeans等。然而,这个列表是可访问的,这样我就可以自动装载MyBean对象列表。

我不能使用类似:

@Configuration 
public Config { 
    @Autowired 
    private SomeConfiguration config; 

    @Bean 
    public MyBean myBean1() { ... } 

    @Bean 
    public MyBean myBean2() { ... } 
} 

由于为myBean的实例数运行之前不知道。我想这样做的原因是因为我们正在控制具有可变数量组件的物理机器。我想每个组件都有一个bean。

我目前使用的BeanFactoryPostProcessor这样实现我们的目标:

@Component 
public class MyBeansFactoryPostProcessor implements BeanFactoryPostProcessor { 
    @Autowired 
    private SomeConfiguration config; 

    @Override 
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeanException { 
     for (Device device : config.getDevices()) { 
      createAndRegister(BeanDefinitionRegistry) beanFactory, device); 
     } 
    } 

    private void createAndRegister(BeanDefinitionRegistry registry, Device device) { 
     register.registerBeanDefinition("device" + device.getId(), BeanDefinitionBuilder.genericBeanDefinition(MyBean.class).addConstructorArgValue(device).getBeanDefinition()); 
    } 
} 

但这只是感觉像一个真正的丑陋的黑客。

+0

对于这个并不罕见的用例,仍然不能接受和很好的回答吗?太疯狂了。 – sebnukem 2018-02-06 02:31:27

回答

2

使用@Configuration不可能为每个方法定义多个bean(AFAIK)。因此,您将不得不使用BFPP或使用ApplicationContect.getAutowireCapableBeanFactory().autowire(object);

+0

感谢这将确保所有@Autowired方法被调用。但它不会将Bean注册到JMX并应用其他后处理。我也试过 'ApplicationContect.getAutowireCapableBeanFactory()。applyBeanPostProcessorsBeforeInitialization(bean,beanName);' 'ApplicationContect.getAutowireCapableBeanFactory()。applyBeanPostProcessorsAfterInitialization(bean,beanName);' 但由于没有bean定义,它们将不会执行完整的后处理。 – pcmoen 2011-05-26 20:56:34

+0

@pcm这是有道理的,那么我想你已经以最好的方式去做了 – 2011-05-26 21:55:09

3

为了注入MyBean列表,请尝试@Resource而不是@Autowired。例如,

@Resource 
public List<MyBean> myBeans 
0

我认为,在这种情况下,另一种选择是通过以下方式使用@PostConstruct:

@Configuration 
public Config { 

@Autowired 
private SomeConfiguration config; 

List<MyBean> beans = new ArrayList<MyBean>(); 

@Bean 
public List<MyBean> myBeans() {  

    return beans; 
} 

@PostConstruct 
public void init() { 
    for (Device device : config.getDevices()) { 
     beans.add(new MyBean(device)); 
    } 
} 
} 

的@PostConstruct注释用于初始化属性很有用。它保证了只有在创建bean时才会调用带注释的方法。

纠正我,如果我错了

0

MyBeans因为它们与new产生,而不是由Spring容器初始化没有后处理。

您需要使用原型bean,每个组件所做的请求都有一个新bean的实例。

您将需要标记像

@Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

MyBean(Device device) bean声明然后调用而不是使用new,你填充beans