Spring 我可以通过编程向bean添加限定符吗?

Spring 我可以通过编程向bean添加限定符吗?,spring,spring-transactions,Spring,Spring Transactions,我在我的代码中注册事务管理器,我通常会使用基于注释的配置,但由于我在运行时之前不知道将有多少数据源(因此也不知道事务管理器),我必须以编程方式注册这些数据源,如下所示: private final void registerTransactionManagerBean(final DataSource dataSource, ConfigurableApplicationContext context) { String transactionManagerName = this.ge

我在我的代码中注册事务管理器,我通常会使用基于注释的配置,但由于我在运行时之前不知道将有多少数据源(因此也不知道事务管理器),我必须以编程方式注册这些数据源,如下所示:

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);
}
假设此.getName()返回“mydb”,我最初希望能够限定如下事务管理器:

@Transactional("mydb-transactionManager")
然而,我意识到注释的值指的是限定符,而不是名称。我做了一个快速测试,声明了一个bean,如下所示:

@Bean
@Qualifier("mydb-transactionManager")
public PlatformTransactionManager test() {
    return new DataSourceTransactionManager(new EmbeddedDatabaseBuilder().build());
}
我的问题是,有没有一种方法可以在注册bean时以编程方式添加限定符

更新
我已经解决了这个问题,但我遇到了这个问题(在BeanFactoryAnnotationUtils:isQualifierMatch中):


我正在手动注册我的事务管理器bean,所以我想这就是我被卡住的原因。我真的不知道除了不以编程方式将事务管理器注册为运行时对象之外,还有什么别的选择。遗憾的是,我已经解决了这个问题,我遇到了这个问题:

catch (NoSuchBeanDefinitionException ex) {
// ignore - can't compare qualifiers for a manually registered singleton object
}
我正在手动注册我的事务管理器bean,所以我想这就是我被卡住的原因。我真的不知道除了不以编程方式将事务管理器注册为运行时对象之外,还有什么其他选择


作为JIRA问题提出-

只需以编程方式使用您想要的名称注册bean即可。我需要:context.getBeanFactory().registerSingleton(transactionManagerName,new DataSourceTransactionManager(dataSource));问题是我需要注册的不是名字,而是限定符。为什么需要注册限定符?你不能用它的名字获得程序注册的bean吗?我想使用注解@Transactional。如果您有多个事务管理器,那么您需要通过限定符名称引用它们-并且使用bean名称作为限定符值不起作用?
catch (NoSuchBeanDefinitionException ex) {
// ignore - can't compare qualifiers for a manually registered singleton object
}
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;
        }
    }
}