繁体   English   中英

如何在启动时以编程方式将 spring bean 标记为 @Primary?

[英]How to programmatically mark a spring bean as @Primary on startup?

我的应用程序中有多个DataSource

标准的org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration@ConditionalOnSingleCandidate(DataSource.class)注释

我正在尝试以编程方式选择@Primary DataSource

我尝试了一个BeanFactoryPostProcessor ,它天真地选择了第一个 DataSource 并将其标记为主要的):

    @Bean
    public BeanFactoryPostProcessor beanFactoryPostProcessor() {
        return this::setPrimaryDataSource;
    }

    public void setPrimaryDataSource(ConfigurableListableBeanFactory beanFactory) {

        // Get all DataSource bean names
        String[] dataSourceBeanNames = beanFactory.getBeanNamesForType(DataSource.class);

        // Find primaryBeanName
        String primaryBeanName = dataSourceBeanNames.length > 0 ? dataSourceBeanNames[0] : null;

        // Return appropriate bean
        assert primaryBeanName != null;
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(primaryBeanName);
        beanDefinition.setPrimary(true);
        LOGGER.info("Primary DataSource: {}", primaryBeanName);

    }

但是,这似乎不起作用 - 对HibernateJpaConfiguration@ConditionalOnSingleCandidate(DataSource.class)检查仍然失败。

有没有其他地方可以放置此代码,以便在检查@ConditionalOnSingleCandidate之前执行它?

如果您的代码在带有@Configuration 的类中,则该方法需要是静态的,以便在创建任何 bean 之前更新 bean 定义。

这是 PropertySourcesPlaceholderConfigurer 的示例。

@Configuration
public class AppConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
         return new PropertySourcesPlaceholderConfigurer();
    }

}

文档中

您可以将@Bean 方法声明为静态方法,允许在不将其包含的配置类创建为实例的情况下调用它们。 这在定义后处理器 bean(例如,BeanFactoryPostProcessor 或 BeanPostProcessor 类型)时特别有意义,因为此类 bean 在容器生命周期的早期被初始化,并且应避免在那时触发配置的其他部分。

BeanFactoryPostProcessor为我工作:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        // logic to retrieve your bean name
        String beanName = beanFactory.getBeanNamesForType(MyService.class)[0];
        
        BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
        bd.setPrimary(true);
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM