我可以以编程方式向bean添加限定符吗?

时间:2014-06-24 11:12:19

标签: spring spring-transactions

我正在我的代码中注册事务管理器,我通常会使用基于注释的配置,但是直到运行时我才知道有多少数据源(以及事务管理器),我必须以编程方式注册这些,如如下:

private final void registerTransactionManagerBean(final DataSource dataSource,ConfigurableApplicationContext context){

String transactionManagerName = this.getName() + "-transactionManager";

context.getBeanFactory().registerSingleton(transactionManagerName, new DataSourceTransactionManager(dataSource));

LOG.info("Registering transaction manager under name : " + transactionManagerName);

}

假设this.getName()返回'mydb',我最初希望能够像这样限定一个transacton管理器:

@Transactional("mydb-transactionManager")

然而,我所意识到的是,该注释的价值是指限定符而不是名称。我通过声明下面的bean来进行快速测试,它可以工作:

@Bean
@Qualifier("mydb-transactionManager")
public PlatformTransactionManager test() {
    return new DataSourceTransactionManager(new EmbeddedDatabaseBuilder().build());
}

我的问题是,有没有办法在注册bean时以编程方式添加限定符?

非常感谢。

更新

我已经解决了这个问题,我正在犯这个问题(在BeanFactoryAnnotationUtils:isQualifierMatch中):

catch (NoSuchBeanDefinitionException ex) {
// ignore - can't compare qualifiers for a manually registered singleton object
}

我手动注册我的事务管理器bean所以我认为这就是为什么我被卡住了。我不确定哪些选项让我与众不同,不能以编程方式将事务管理器注册为运行时事件。

2 个答案:

答案 0 :(得分:0)

我已经解决了这个问题,我正在犯这个问题:

catch (NoSuchBeanDefinitionException ex) {
// ignore - can't compare qualifiers for a manually registered singleton object
}

我手动注册我的事务管理器bean所以我认为这就是为什么我被卡住了。我不确定哪些选项让我与众不同,不能以编程方式将事务管理器注册为运行时事件。

提出JIRA问题 - https://jira.spring.io/browse/SPR-11915

答案 1 :(得分:0)

public class RuntimeRegistrationWithQualifierTest {
    private AnnotationConfigApplicationContext context;

    @Test
    public void beanWithQualifier() {

        final GenericBeanDefinition helloBeanDefinition = new GenericBeanDefinition();
        helloBeanDefinition.addQualifier(new AutowireCandidateQualifier(Hello.class));

        final GenericBeanDefinition worldBeanDefinition = new GenericBeanDefinition();
        worldBeanDefinition.addQualifier(new AutowireCandidateQualifier(World.class));

        final DefaultListableBeanFactory factory = context.getDefaultListableBeanFactory();

        factory.registerBeanDefinition("helloBean", helloBeanDefinition);
        factory.registerSingleton("helloBean", "hello");

        factory.registerBeanDefinition("worldBean", worldBeanDefinition);
        factory.registerSingleton("worldBean", "world");

        context.register(Foo.class);

        context.refresh();

        final Foo foo = context.getBean(Foo.class);

        assertThat(foo.hello).isEqualTo("hello");
        assertThat(foo.world).isEqualTo("world");
    }

    @Before
    public void newContext() {
        context = new AnnotationConfigApplicationContext();
    }

    @Qualifier
    @Retention(RUNTIME)
    @Target({FIELD, PARAMETER})
    @interface Hello {}

    @Qualifier
    @Retention(RUNTIME)
    @Target({FIELD, PARAMETER})
    @interface World {}

    static class Foo {
        final String hello;
        final String world;

        Foo(@Hello final String hello, @World final String world) {
            this.hello = hello;
            this.world = world;
        }
    }
}