基于Java的Config,用于创建Parameterized Singleton Spring Bean

时间:2017-03-28 20:29:40

标签: java spring inversion-of-control javabeans

我在XML中有以下bean定义列表:

<bean id="version201627" class="predicate.ClientVersionPredicate">
    <property name="year" value="2016"/>
    <property name="week" value="27"/>
</bean>

<bean id="version201628" class="predicate.ClientVersionPredicate">
    <property name="year" value="2016"/>
    <property name="week" value="28"/>
</bean>

... // the list goes on

有没有办法将其转换为基于Java的@Configuration,而不是创建这么多方法?

类似的东西:

@Bean
public ClientVersionPredicate somePredicate(String year, String week) {
    return new ClientVersionPredicate(year, week);
}

但我可以在某处指定args吗?感谢。

3 个答案:

答案 0 :(得分:0)

可以使用BeanDefinitionRegistryPostProcessorJavadoc)和BeanDefinitionBuilder完成此操作。

@Component
public class ClientVersionPredicateDefiner implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
            throws BeansException {
        // no need for post processing
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
            throws BeansException {
        IntStream.range(27, 47).forEach(week -> {
            String year = "2016";
            BeanDefinitionBuilder builder = BeanDefinitionBuilder
                    .genericBeanDefinition(ClientVersionPredicate.class);
            builder.addPropertyValue("year", year);
            builder.addPropertyValue("week", String.valueOf(week));
            registry.registerBeanDefinition("version" + year + week, 
                    builder.getBeanDefinition());
        });
    }

}

对于此示例,我假设您在2016年需要一个版本27到46周。您如何定义配置值取决于您(并根据您的实际配置需求)。

现在可以通过名称获取bean:

ClientVersionPredicate version201627 = ctx.getBean("version201627");
ClientVersionPredicate version201628 = ctx.getBean("version201628");
...

答案 1 :(得分:0)

您可以使用GenericBeanDefintion(查看here了解更多详情),这有助于定义&amp;动态注册bean。

以下代码使用GenericBeanDefintion&amp;帮助您在应用程序启动期间通过单个方法定义所需的bean。

基本上,您需要一个包含数年和数周的对象列表(List<YearAndWeek> yearAndWeeks),或者您可以使用包含数据和数据的任何其他集合/数组。然后迭代它以使用bean注册表注册bean。

@Component
public class MyProjectSpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) 
           throws BeansException {
           MyProjectSpringUtil.applicationContext = applicationContext;
    }

    @PostConstruct
    public void addNewBeans() {
        AutowireCapableBeanFactory factory = 
                 applicationContext.getAutowireCapableBeanFactory();
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;

       //Get your years and weeks data here through objects or array
        List<YearAndWeek> yearAndWeeks = new ArrayList<>();

        for(int i=0;i<yearAndWeeks.size();i++) {
             YearAndWeek yearAndWeek = yearAndWeeks.get(i);

             GenericBeanDefinition clientVersionPredicate = 
                                      new GenericBeanDefinition();
             clientVersionPredicate.setBeanClass(ClientVersionPredicate.class);
             clientVersionPredicate.setScope(
                GenericBeanDefinition.SCOPE_SINGLETON);
             MutablePropertyValues props = new MutablePropertyValues();
             props.add("year", yearAndWeeks.getYear());
             props.add("week", yearAndWeeks.getWeek());
             clientVersionPredicate.setPropertyValues();

             //register your bean with id & object
             registry.registerBeanDefinition(
                      "version"+yearAndWeek,getYear()+yearAndWeek,getMonth(), 
                      clientVersionPredicate);
        }
    }
}

YearAndWeek课程:

public class YearAndWeek {
    private int year;

    private int week;

   //getters and setters
}

答案 2 :(得分:0)

您可以使用外部化属性文件来包含Bean的年和周值。属性的示例可能如下所示......

version201627.year=2016
version201627.week=27

version201628.year=2016
version201628.week=28

然后在你的java配置文件中,你可以这样做......

@Bean
@ConfigurationProperties(prefix="version201627")
public ClientVersionPredicate version201627() {
    return new ClientVersionPredicate();
}

@Bean
@ConfigurationProperties(prefix="version201628")
public ClientVersionPredicate version201628() {
    return new ClientVersionPredicate();
}