2011-05-26 78 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