程序化Bean注册

时间:2017-10-04 15:57:23

标签: spring spring-integration

我想了解@Bean注释bean注册的程序化等价物

假设我有一个这样的课程:

@Configuration
public class SimpleConfiguration {
    @Bean
    public BigDecimal aDecimal( String example ) {
        return new BigDecimal( example );
    }
}

这是我认为在这里发生的事情:

  1. 以某种方式将Spring注册为一个名为bean的工厂 BigDecimal类型的“aDecimal”,依赖于类型的bean 串
  2. 在某些时候,将使用正确的bean调用此方法 参数和结果将是与之关联的实例 “aDecimal”bean。
  3. 如果我想用这样的东西做同样的事情:

    @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)

2 个答案:

答案 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" ) );
    }
}
相关问题