使用@Configuration在Spring中创建bean集合

pcm*_*oen 17 java collections configuration spring annotations

如何使用带有@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但MyBean实例未经过后期处理.所以他们的@Autowired方法没有被调用,bean没有被注册为mbeans等.但是这个列表是可访问的,所以我可以自动装配一个MyBean对象列表.

我不能使用像:

@Configuration
public Config {
    @Autowired
    private SomeConfiguration config;

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

    @Bean
    public MyBean myBean2() { ... }
}
Run Code Online (Sandbox Code Playgroud)

由于在运行时之前不知道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());
    }
}
Run Code Online (Sandbox Code Playgroud)

但这只是一个非常丑陋的黑客.

Sla*_*des 6

您可以使用ConfigurableListableBeanFactorywhich 支持SmartLifecycle,因此如果您在应用程序完全初始化之前注册 bean,它将调用start()您和其他后处理步骤。

然而,如果你beanFactory.registerSingleton在 spring 初始化后调用,你将需要手动调用start()- 好的一面是,尽管你的 bean 仍然完全连接到生命周期管理中,并且 spring 会stop()在应用程序上下文关闭时为你调用。

@Autowired
private ConfigurableListableBeanFactory beanFactory;

@Bean
public List<MyBean> myBeansList() {

    List<MyBean> mylist; // Construct your list dynamically

    while(myCondition) {
        MyBean bean;
        // Manually register each instance with Spring
        beanFactory.registerSingleton("unique-name-for-this-bean",bean);
    }

    // Return your list as a bean so you can still autowire the list of beans
    // but each bean has already been manually added to the context
    return mylist;
}
Run Code Online (Sandbox Code Playgroud)


Sea*_*oyd 2

不可能为@Configuration每个方法定义多个 bean(AFAIK)。所以你必须继续使用 BFPP 或使用ApplicationContect.getAutowireCapableBeanFactory().autowire(object);