使用@Configuration在春季创建豆类集合

我如何创建一个bean集合,这些bean将由Spring使用具有@Configuration注释的类进行正确管理。

我想做这样的事情:

@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方法不被调用,豆子没有被注册为mbeans等。但是,该列表是可访问的,因此我可以自动连接MyBean对象列表。

我不能使用类似的东西:

@Configuration
public Config {
    @Autowired
    private SomeConfiguration config;

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

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

由于 MyBean 实例的数量在运行时之前是未知的。我想这样做的原因是因为我们控制着一台具有可变数量组件的物理机器。我想每个组件有一个豆子。

我目前正在通过使用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());
    }
}

但这感觉就像一个非常丑陋的黑客。


答案 1

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

@Resource
public List<MyBean> myBeans

答案 2

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

但是 - 如果您在spring初始化后调用,您将需要手动调用 - 从好的方面来说,尽管您的bean仍然完全连接到生命周期管理中,并且spring将在应用程序上下文关闭时调用您。beanFactory.registerSingletonstart()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;
}