我想了解@Bean注释bean注册的程序化等价物
假设我有一个这样的课程:
@Configuration
public class SimpleConfiguration {
@Bean
public BigDecimal aDecimal( String example ) {
return new BigDecimal( example );
}
}
这是我认为在这里发生的事情:
如果我想用这样的东西做同样的事情:
@Configuration
public class DynamicConfiguration {
public void registerDefinition() {
/* i know it can't be like this but i hope it's clear what i mean */
register( "aDecimal", (example) -> aDecimal( example ) );
}
public BigDecimal aDecimal( String example ) {
/* this could be any kind of complex bean creation method */
return new BigDecimal( example );
}
}
实现这一结果的正确方法是什么?
我已经研究了一下这个,我找到了例如
How do I create beans programmatically in Spring Boot?
但是这种注册似乎没有注释那么强大,让我们弹出实例化bean,我希望bean通过提供的方法进行实例化
How to programmatically create bean definition with injected properties?
并且缺少使用注入的bean参数调用方法的能力。
我想要这样做的原因是,我有一些配置类,它们根据配置文件包含许多具有不同限定符的bean。 现在每次配置文件扩展时,我都需要添加新的bean和配置(其中很多是Spring SessionFactories和SpringIntegration流程,所以我需要这些东西成为spring bean)
答案 0 :(得分:2)
您需要考虑使用IntegrationFlowContext
:
@Autowired
private IntegrationFlowContext integrationFlowContext;
...
IntegrationFlow myFlow = f -> ...;
BeanFactoryHandler additionalBean = new BeanFactoryHandler();
IntegrationFlowRegistration flowRegistration =
this.integrationFlowContext.registration(myFlow)
.addBean(additionalBean)
.register();
它为您提供了在运行时注册其他bean的钩子,而不仅仅是IntegrationFlow
结构。
答案 1 :(得分:1)
我找到了解决问题的方法,这一切都发生在BeanDefinition“阶段”,这样一切都由spring管理,并且工作方式与注入参数的@Bean注释方法完全相同,它还在注释之间干净地桥接和以编程方式注册的bean。
这就是我做的事情
@Configuration
@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = { TestSpringDynamicConfiguration.class } )
public class TestSpringDynamicConfiguration implements BeanDefinitionRegistryPostProcessor {
@Autowired
@Qualifier( "qualified" )
private String dynamicString;
@Bean
public Integer zero() {
return 0;
}
public String zeroString( Integer aInteger ) {
return aInteger.toString();
}
@Override
public void postProcessBeanDefinitionRegistry( final BeanDefinitionRegistry registry ) throws BeansException {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setAutowireMode( GenericBeanDefinition.AUTOWIRE_CONSTRUCTOR );
beanDefinition.setScope( BeanDefinition.SCOPE_SINGLETON );
beanDefinition.setFactoryBeanName( "testSpringDynamicConfiguration" );
beanDefinition.setFactoryMethodName( "zeroString" );
registry.registerBeanDefinition( "qualified", beanDefinition );
}
@Override public void postProcessBeanFactory( final ConfigurableListableBeanFactory beanFactory ) throws BeansException { }
@Test
public void testDynamicConfiguration() throws Exception {
assertThat( dynamicString, is( "0" ) );
}
}