Spring 自动将多个列表连接到一个列表中

Spring autowire multiple lists into one list

提问人:JimBob 提问时间:8/8/2023 更新时间:8/8/2023 访问量:57

问:

有没有办法自动连接某种类型的列表,自动合并多个列表 bean?

@Configuration
public class MyConfig {
  
  @Bean
  List<MyAbstractClass> getList1()...

  @Bean
  List<MyAbstractClass> getList2()...

}

@Component
public class MyComponent {

  @Autowired
  List<MyAbstractClass> combinedList1AndList2;

}

目前春天告诉我:

考虑将其中一个 Bean 标记为 @Primary,更新使用者 接受多个 Bean,或使用 @Qualifier 来标识 Bean 应该消耗的

提前致谢。

Java Spring 自动连线

评论


答:

0赞 Turan-Yahya Gazizuly 8/8/2023 #1

为您的示例添加额外的内容。一种方法是创建一个聚合要组合的内容,然后在需要时聚合该组合。codecustom collection beanlistsautowirecustom collection bean

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class MyComponent {

    private final List<MyAbstractClass> combinedList;

    @Autowired
    public MyComponent(CombinedList combinedListBean) {
        this.combinedList = combinedListBean.getCombinedList();
    }

    // Use the combinedList as needed
}

Autowire用于组件custom collection bean

import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class CombinedList {
    private final List<MyAbstractClass> list1;
    private final List<MyAbstractClass> list2;

    public CombinedList(List<MyAbstractClass> list1, List<MyAbstractClass> list2) {
        this.list1 = list1;
        this.list2 = list2;
    }

    public List<MyAbstractClass> getCombinedList() {
        List<MyAbstractClass> combinedList = new ArrayList<>(list1);
        combinedList.addAll(list2);
        return combinedList;
    }
}

评论

0赞 JimBob 8/8/2023
谢谢你的建议。实际上,我一直在寻找一种更通用/自动的方式,因为这些列表 bean 将超过 8 个。如果我想多次重用组合的组件,通过在另一个组件中单独自动连接它们是有意义的。但我只需要在一个组件中使用它们。我正在考虑BeanFactoryPostProcessor的方向,但不确定是否有更简单的方法。
0赞 Turan-Yahya Gazizuly 8/8/2023 #2

另一个答案,试试吧!

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class CombineListsPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // Define a list to hold the combined beans
        List<Object> combinedList = new ArrayList<>();

        // Retrieve and merge lists from the bean factory
        ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory) registry;
        for (String beanName : beanFactory.getBeanNamesForType(List.class)) {
            combinedList.addAll(beanFactory.getBean(beanName, List.class));
        }

        // Create a new bean definition for the combined list
        BeanDefinition combinedListBeanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(ArrayList.class, () -> combinedList).getBeanDefinition();

        // Register the combined list bean definition
        registry.registerBeanDefinition("combinedList", combinedListBeanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // No additional processing needed here
    }
}

评论

0赞 JimBob 8/8/2023
哦,谢谢!这看起来几乎和我的想法差不多。同时,我在配置中使用了一种更简单的方法,与您最初建议的方法相当。BeanFactoryPostProcessor 将事情混淆到很多......如果不进行测试,我会说这个答案是正确的。