如何为来自不同 属性 文件的 Bean 列表配置 Spring 配置?

How to configure Spring configuration for List of Beans from different property files?

我有工作 Spring XML 配置,我想将它移动到 Annotation Config。

问题是如何从不同的 属性 文件创建不同的 bean。

这是 XML 片段:

<bean id="auditorium1" class="net.lelyak.edu.entity.Auditorium"
      c:name="${auditorium1.name}" c:numberOfSeats="${auditorium1.number-of-seats}" 
      c:vipSeats="${auditorium1.vip-seats}"/>
<bean id="auditorium2" class="net.lelyak.edu.entity.Auditorium"
      c:name="${auditorium2.name}" c:numberOfSeats="${auditorium2.number-of-seats}" 
      c:vipSeats="${auditorium2.vip-seats}"/>
<bean id="auditorium3" class="net.lelyak.edu.entity.Auditorium"
      c:name="${auditorium3.name}" c:numberOfSeats="${auditorium3.number-of-seats}" 
      c:vipSeats="${auditorium3.vip-seats}"/>

<util:list id="auditoriumsList">
    <ref bean="auditorium1"/>
    <ref bean="auditorium2"/>
    <ref bean="auditorium3"/>
</util:list>

<bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean" /> 

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:properties/auditorium1.properties</value>
            <value>classpath:properties/auditorium2.properties</value>
            <value>classpath:properties/auditorium3.properties</value>
            <value>classpath:db/dp.properties</value>
        </list>
    </property>
    <property name="ignoreResourceNotFound" value="true"/>
    <property name="systemPropertiesMode">
        <util:constant
                static-field="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
    </property>
</bean>

属性 文件示例:

auditorium1.name=yellow
auditorium1.number-of-seats=150
auditorium1.vip-seats=1,2,3,4,5,6,7,8,9

我想将其移至注释配置,例如:

@Configuration
public class AuditoriumConfiguration {

    @Bean
    public Auditorium auditorium1() {
        return new Auditorium();
    }

    @Bean
    public Auditorium auditorium2() {
        return new Auditorium();
    }

    @Bean
    public Auditorium auditorium3() {
        return new Auditorium();
    }

    @Bean
    public List<Auditorium> auditoriumsList() {
        return Arrays.asList(auditorium1(), auditorium2(), auditorium3());
    }

    @Bean
    public ConversionService conversionService() {
        return new DefaultConversionService();
    }
}

这里是 Auditorium POJO:

@Component
public class Auditorium {
    private Integer id;
    private String name;
    private Integer numberOfSeats;
    private Set<Integer> vipSeats;
    // get / set

如何为每个 属性 文件创建不同的 Auditorium 实例?

我想我可以使用 @Value,但我找不到为每个 属性 文件创建对象的方法。

有什么建议吗?

首先您不需要列表,如果您需要类型列表,只需将 @Autowired 添加到集合中,然后 spring 会将那个 bean 的所有类型注入到那个集合中。

要获取属性,您可以使用 Environment 并且您可能想为此添加一个 helper/factory 方法。

默认情况下已配置转换服务,因此无需添加。

要加载配置文件,请将 @PropertySource 添加到您的配置 class。如果您需要 @Value 或替换占位符,则需要添加 PropertySourcesPlaceholderConfigurer 作为 static bean。

基本上,像这样的东西应该可以达到你想要的效果。

@Configuration
@PropertySource({"classpath:properties/auditorium1.properties",
        "classpath:properties/auditorium2.properties",
        "classpath:properties/auditorium3.properties",
        "classpath:db/dp.properties"})
public class AuditoriumConfiguration {

    @Autowired
    private Environment env;

    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    private Auditorium createAuditorium(String prefix) {
        String nameString = env.getProperty(prefix + ".name");
        String strNumberOfSeats = env.getProperty(prefix + ".number-of-seats");
        Integer[] integers = env.getProperty(prefix + ".vip-seats", Integer[].class);
        Set<Integer> integerSet = Arrays.stream(integers).collect(Collectors.toSet());

        Auditorium auditorium = new Auditorium();
        auditorium.setName(nameString);
        auditorium.setNumberOfSeats(Integer.valueOf(strNumberOfSeats));
        auditorium.setVipSeats(integerSet);
        return auditorium;
    }

    @Bean
    public Auditorium auditorium1() {
        return createAuditorium("auditorium1");
    }

    @Bean
    public Auditorium auditorium2() {
        return createAuditorium("auditorium2");
    }

    @Bean
    public Auditorium auditorium3() {
        return createAuditorium("auditorium3");
    }
}

现在,如果您想要这些 classes 的列表,只需添加一个 List<Auditorium>,然后 spring 会将所有依赖项注入该列表。

public class MyClass {
    @Autowired
    private List<Auditorium> auditoriums;
}
@Configuration
public class DataSourceConfig {
    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(...);
    }
}

@Configuration
@Import({ DataSourceConfig.class, TransactionConfig.class })
public class AppConfig extends ConfigurationSupport {
    // bean definitions here can reference bean definitions in DataSourceConfig or TransactionConfig
}


@Configuration
@PropertySource("classpath:/com/myco/app.properties")
//@ResourceBundles("classpath:/org/springframework/config/java/simple")

public class AppConfig {

    @Value("${jdbc.url}")
    //@ExternalValue("datasource.username")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;
    
     @Bean
    public TestBean testBean () {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("one", 1);
        map.put("two", 2);
        return new TestBean(map);
    }
    
    @Bean
public Map<Integer, String> nameMap(){
    Map<Integer, String>  nameMap = new HashMap<>();
    nameMap.put(1, "John");
    nameMap.put(2, "Adam");
    nameMap.put(3, "Harry");
    return nameMap;
}

private Map<Integer, String> nameMap;
 
    @Autowired
    public void setNameMap(Map<Integer, String> nameMap) {
        this.nameMap = nameMap;
    }
 
    public void printNameMap() {
        System.out.println(nameMap);
    }
    
    

@Bean
    public List<String> nameList() {
        return Arrays.asList("John", "Adam", "Harry");
    }
    
    //set 
    private Set<String> nameSet;
 
    public AppConfig(Set<String> strings) {
        this.nameSet = strings;
    }
 
 @Bean
public AppConfig getCollectionsBean() {
    return new AppConfig(new HashSet<>(Arrays.asList("John", "Adam", "Harry")));
}


 
    public void printNameSet() {
     
   System.out.println(nameSet);
    }
    
    
    private Set<String> nameSet;
 
    public AppConfig(Set<String> strings) {
        this.nameSet = strings;
    }
 
    public void printNameSet() {
        System.out.println(nameSet);
    }
    
    
    

    
    }
    
    public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    TestBean bean = context.getBean(TestBean.class);
        System.out.println(bean.getMap());
}