创建参数化单例Springbean的基于Java的配置
我有以下XML形式的bean定义列表:创建参数化单例Springbean的基于Java的配置,java,spring,inversion-of-control,javabeans,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.Clien
<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
但是我可以在某个地方指定参数?谢谢。这可以使用
BeanDefinitionRegistryPostProcessor
()和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");
...
您可以使用
genericbeandefinition
(查看更多详细信息),这有助于动态定义和注册bean
下面的代码使用genericbeandefinition
&帮助您在应用程序启动期间通过单个方法定义所需的bean
基本上,您需要一个包含年和周的对象列表(List 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);
}
}
}
您可以使用外部化属性文件来包含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();
}
有没有办法让1个方法代替2个?我目前有20个XMLBean def,我更愿意将其简化为1个方法……对不起,我还没有看到这是您的主要观点。您真的需要不同的bean定义(每个bean都有一个唯一的id)还是一个具有不同初始化值的原型可以吗?我的错,我刚刚看到您在寻找单例Bean定义注册表后处理将是一条可行之路。。
version201627.year=2016
version201627.week=27
version201628.year=2016
version201628.week=28
@Bean
@ConfigurationProperties(prefix="version201627")
public ClientVersionPredicate version201627() {
return new ClientVersionPredicate();
}
@Bean
@ConfigurationProperties(prefix="version201628")
public ClientVersionPredicate version201628() {
return new ClientVersionPredicate();
}