All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.autoconfigure.datasource.jdbc.JdbcDataSourceConfigAutoConfiguration Maven / Gradle / Ivy

There is a newer version: 1.6.8
Show newest version
package org.zodiac.autoconfigure.datasource.jdbc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.zodiac.autoconfigure.datasource.condition.ConditionalOnDataSourceEnabled;
import org.zodiac.commons.constants.Constants;
import org.zodiac.commons.constants.SystemPropertiesConstants;
import org.zodiac.commons.util.Asserts;
import org.zodiac.commons.util.Colls;
import org.zodiac.commons.util.lang.Strings;
import org.zodiac.datasource.jdbc.beecp.BeeDataSourceWrapper;
import org.zodiac.datasource.jdbc.callback.DynamicDataSourceCallback;
import org.zodiac.datasource.jdbc.config.DataSourceRuleInfo;
import org.zodiac.datasource.jdbc.constants.DataSourceConstants;
import org.zodiac.datasource.jdbc.constants.DataSourceSystemPropertiesConstants;
import org.zodiac.datasource.jdbc.dbcp2.BasicDataSourceWrapper;
import org.zodiac.datasource.jdbc.druid.DruidDataSourceWrapper;
import org.zodiac.datasource.jdbc.dynamic.DynamicDataSourceAnnotationAdvisor;
import org.zodiac.datasource.jdbc.dynamic.DynamicDataSourceAnnotationInterceptor;
import org.zodiac.datasource.jdbc.dynamic.DynamicDataSourceHolder;
import org.zodiac.datasource.jdbc.exception.DataSourceSQLException;
import org.zodiac.datasource.jdbc.factory.DataSourceFactory;
import org.zodiac.datasource.jdbc.factory.DefaultDataSourceFactory;
import org.zodiac.datasource.jdbc.factory.DynamicDataSourceFactory;
import org.zodiac.datasource.jdbc.hikari.HikariCPDataSourceWrapper;
import org.zodiac.datasource.jdbc.transaction.DataSourceTransactionalAnnotationAdvisor;
import org.zodiac.datasource.jdbc.transaction.DataSourceTransactionalAnnotationInterceptor;
import org.zodiac.datasource.jdbc.util.DataSourceUtil;

import javax.sql.DataSource;

import java.sql.SQLException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

@SpringBootConfiguration
@ConditionalOnDataSourceEnabled
//@AutoConfigureBefore(value = {DataSourceAutoConfiguration.class})
@AutoConfigureAfter(value = {JdbcDataSourceRuleAutoConfiguration.class})
@ConditionalOnClass(name = {"org.zodiac.datasource.config.DataSourceConfigInfo"})
//@AutoConfigureAfter(value = {JdbcDataSourcePoolAutoConfiguration.class, JdbcDataSourceRuleAutoConfiguration.class})
@Import(value = {JdbcDataSourceConfigAutoConfiguration.DataSourceBeanPostProcessor.class, JdbcDataSourceConfigAutoConfiguration.DataSourceRegistrar.class})
public class JdbcDataSourceConfigAutoConfiguration {

    private static final Logger LOGGER = LoggerFactory.getLogger(JdbcDataSourceConfigAutoConfiguration.class);

    private Environment environment;

    public JdbcDataSourceConfigAutoConfiguration(Environment environment) {
        this.environment = environment;
    }

    @Bean
    @Order(value = Ordered.HIGHEST_PRECEDENCE)
    @ConditionalOnProperty(name = SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_ROUTING_ENABLED, havingValue = "true", matchIfMissing = true)
    protected DynamicDataSourceAnnotationAdvisor
        dynamicDatasourceAnnotationAdvisor(DynamicDataSourceCallback dynamicDataSourceCallback) {
        DynamicDataSourceAnnotationInterceptor interceptor =
            new DynamicDataSourceAnnotationInterceptor(dynamicDataSourceCallback);
        DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);
        return advisor;
    }

    @Bean
    @ConditionalOnMissingBean
    protected DynamicDataSourceCallback dynamicDataSourceCallback() {
        return new DynamicDataSourceCallback() {
            @Override
            public void setDefaultDataSource() {
                if (!DataSourceUtil.useCustomizedDataSource()) {
                    DynamicDataSourceHolder.pushDataSource(DataSourceUtil.getDynamicDefaultDataSource());
                }
            }
        };
    }

    @Bean
    @Order(value = Ordered.LOWEST_PRECEDENCE)
    @ConditionalOnProperty(name = SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_TRANSACTION_ENABLED, havingValue = "true", matchIfMissing = true)
    protected DataSourceTransactionalAnnotationAdvisor dataSourceTransactionalAnnotationAdvisor() {
        DataSourceTransactionalAnnotationInterceptor interceptor = new DataSourceTransactionalAnnotationInterceptor();
        DataSourceTransactionalAnnotationAdvisor advisor = new DataSourceTransactionalAnnotationAdvisor(interceptor);
        return advisor;
    }

    @Bean
    @ConditionalOnMissingBean(value = {PlatformTransactionManager.class})
    @ConditionalOnProperty(name = SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_TRANSACTION_MANAGER_ENABLED, havingValue = "true", matchIfMissing = true)
    protected DataSourceTransactionManager transactionManager(@Qualifier(DataSourceConstants.DATA_SOURCE_NAME) DataSource datasource,
        ObjectProvider transactionManagerCustomizers) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(datasource);
        if (transactionManagerCustomizers != null
            && transactionManagerCustomizers instanceof TransactionManagerCustomizers) {
            TransactionManagerCustomizers txCustomizers =
                (TransactionManagerCustomizers)transactionManagerCustomizers.getIfAvailable();
            if (txCustomizers != null) {
                txCustomizers.customize(transactionManager);
            }
        }
        return transactionManager;
    }

    /*覆盖initializer,正常情况下不需要这个组件。*/
    @Bean
    @ConditionalOnProperty(name = SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_OVERRIDE_INIT_ENABLED, havingValue = "true", matchIfMissing = true)
    protected DataSourceInitializerPostProcessor dataSourceInitializerPostProcessor(BeanFactory beanFactory) {
        return new DataSourceInitializerPostProcessor(beanFactory);
    }

    static class DataSourceRegistrar implements EnvironmentAware, BeanFactoryPostProcessor, Ordered {

        private Environment environment = null;

        private AtomicBoolean registered = new AtomicBoolean(false);

        /*因为实现“EnvironmentAware”、“BeanFactoryPostProcessor”的类必须有默认构造函数。这里只能使用属性注入,不能使用构造函数注入。而且可以没有开启,所以“required = false”。*/
//        @Autowired(required = false)
//        private DataSourceConfigProperties dataSourceConfigProperties;

        public DataSourceRegistrar() {
            super();
        }

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory)
            throws BeansException {
            boolean dataSourceEnabled = environment.getProperty(SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_ENABLED, boolean.class, false);
            if (!dataSourceEnabled) {
                return;
            }

//            if (configurableListableBeanFactory instanceof BeanDefinitionRegistry && !registered.get()) {
//                registerBeanDefinitions((BeanDefinitionRegistry)configurableListableBeanFactory);
//                registered.set(true);
//            }
            if (configurableListableBeanFactory instanceof BeanDefinitionRegistry) {
                if (registered.compareAndSet(false, true)) {
                    try {
                        registerBeanDefinitions((BeanDefinitionRegistry)configurableListableBeanFactory);
                    } catch (Exception e) {
                        JdbcDataSourceConfigAutoConfiguration.LOGGER.error("{}", e.getMessage());
                        registered.compareAndSet(true, false);
                    }
                }
            }

        }

        @Override
        public void setEnvironment(Environment environment) {
            this.environment = environment;
        }

        private void registerBeanDefinitions(BeanDefinitionRegistry registry) throws DataSourceSQLException {
            /*全部数据连接池名称。*/
            final Set allDsNames = Colls.set();

            boolean autoSetPrimary = environment.getProperty(SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_AUTO_SET_PRIMARY,
                boolean.class, Constants.Zodiac.DEFAULT_DATASOURCE_CONFIG_AUT_SET_PRIMARY);
            boolean dynamicDataSource = environment.getProperty(SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_CONFIG_DYNAMIC_ENABLED,
                boolean.class, Constants.Zodiac.DEFAULT_DATASOURCE_CONFIG_DYNAMIC_ENABLED);
            String primaryDataSource = environment.getProperty(SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_PRIMARY,
                String.class, Constants.Zodiac.DEFAULT_DATASOURCE_PRIMARY);

            /*set 'druid.mysql.usePingMethod' value(default false to avoid 'Communications link failure' when access mysql by proxy)*/
            boolean druidKeepAliveUsePing = environment.getProperty(SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_DRUID_KEEP_ALIVE_USE_PING,
                boolean.class, Constants.Zodiac.DEFAULT_DATASOURCE_DRUID_KEEP_ALIVE_USE_PING);
            System.getProperties().setProperty(DataSourceSystemPropertiesConstants.DRUID_MYSQL_USE_PING_METHOD, String.valueOf(druidKeepAliveUsePing));

            Map dependencyRoots = Colls.map();
            Map dataSourceRules =
                DataSourceUtil.getDataSourceRuleBindings(environment);

            /*BeeCP数据源注册。*/
            Map beeDataSourcePools = DataSourceUtil.getBeeDataSourcePoolBindings(environment);
            for (String key : beeDataSourcePools.keySet()) {
                if (allDsNames.contains(key)) {
                    /*存在重复的数据源名称。*/
                    throw new DataSourceSQLException(String.format("Duplicate data source pool %s is found, please check.", key));
                }
                allDsNames.add(key);

                String dsName = DataSourceUtil.normalizeDataSourceName(key);
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(BeeDataSourceWrapper.class)
                    .setDestroyMethodName("close");

                AbstractBeanDefinition bd = builder.getBeanDefinition();

                /*默认是根。*/
                dependencyRoots.put(key, Boolean.TRUE);
                if (autoSetPrimary && key.equals(primaryDataSource)) {
                    bd.setPrimary(true);
                }

                registry.registerBeanDefinition(dsName, bd);

                LOGGER.info("LoadDataSource: {}", dsName);
            }

            /*Durid数据源注册。*/
            Map druidDataSourcePools = DataSourceUtil.getDruidDataSourcePoolBindings(environment);
            for (String key : druidDataSourcePools.keySet()) {
                if (allDsNames.contains(key)) {
                    /*存在重复的数据源名称。*/
                    throw new DataSourceSQLException(String.format("Duplicate data source pool %s is found, please check.", key));
                }
                allDsNames.add(key);

                String dsName = DataSourceUtil.normalizeDataSourceName(key);
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(DruidDataSourceWrapper.class)
                    .setInitMethodName("init").setDestroyMethodName("close");

                AbstractBeanDefinition bd = builder.getBeanDefinition();

                /*默认是根。*/
                dependencyRoots.put(key, Boolean.TRUE);
                if (autoSetPrimary && key.equals(primaryDataSource)) {
                    bd.setPrimary(true);
                }

                registry.registerBeanDefinition(dsName, bd);

                LOGGER.info("LoadDataSource: {}", dsName);
            }

            /*HikariCP数据源注册。*/
            Map hikariDataSourcePools = DataSourceUtil.getHikariDataSourcePoolBindings(environment);
            for (String key : hikariDataSourcePools.keySet()) {
                if (allDsNames.contains(key)) {
                    /*存在重复的数据源名称。*/
                    throw new DataSourceSQLException(String.format("Duplicate data source pool %s is found, please check.", key));
                }
                allDsNames.add(key);

                String dsName = DataSourceUtil.normalizeDataSourceName(key);
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(HikariCPDataSourceWrapper.class)
                    .setDestroyMethodName("close");

                AbstractBeanDefinition bd = builder.getBeanDefinition();

                /*默认是根。*/
                dependencyRoots.put(key, Boolean.TRUE);
                if (autoSetPrimary && key.equals(primaryDataSource)) {
                    bd.setPrimary(true);
                }

                registry.registerBeanDefinition(dsName, bd);

                LOGGER.info("LoadDataSource: {}", dsName);
            }


            if (!allDsNames.contains(primaryDataSource)) {
                /*主数据源名称在配置数据源名称中不存在。*/
                throw new DataSourceSQLException(String.format("The absent primary data source pool %s in the given data sources, please check.", primaryDataSource));
            }

            /*根据Rules设置注册bean。*/
            for (Entry rule : dataSourceRules.entrySet()) {

                String dataSourceFactoryBeanName = null;
                Class dataSourceFactoryBeanClass = null;

                if (rule.getValue().getSharding() != null) {
                    dataSourceFactoryBeanClass = org.zodiac.datasource.jdbc.factory.ShardingDataSourceFactory.class;
                } else if (rule.getValue().getMasterSlave() != null) {
                    dataSourceFactoryBeanClass = org.zodiac.datasource.jdbc.factory.MasterSlaveDataSourceFactory.class;
                } else if (rule.getValue().getSingle() != null) {
                    dataSourceFactoryBeanClass = org.zodiac.datasource.jdbc.factory.SingleDataSourceFactory.class;
                } else if (rule.getValue().getEncrypt() != null) {
                    LOGGER.warn("Should NOT enter this condition for rule:{}, please check your configuration",
                        rule.getKey());
                    dataSourceFactoryBeanClass = org.zodiac.datasource.jdbc.factory.EncryptDataSourceFactory.class;
                }

                dataSourceFactoryBeanName = rule.getKey() + dataSourceFactoryBeanClass.getSimpleName();
                BeanDefinitionBuilder factoryBuilder =
                    BeanDefinitionBuilder.genericBeanDefinition(dataSourceFactoryBeanClass);
                factoryBuilder.addConstructorArgValue(rule);
                registry.registerBeanDefinition(dataSourceFactoryBeanName, factoryBuilder.getBeanDefinition());

                BeanDefinition bd = new GenericBeanDefinition();
                bd.setFactoryBeanName(dataSourceFactoryBeanName);
                bd.setFactoryMethodName("getDataSource");

                String dataSourceName = DataSourceUtil.normalizeDataSourceName(rule.getKey());
                registry.registerBeanDefinition(dataSourceName, bd);

                dependencyRoots.put(rule.getKey(), Boolean.TRUE);

                rectifyDependencyRoots(rule, dependencyRoots);

                if (autoSetPrimary && rule.getKey().equals(primaryDataSource)) {
                    bd.setPrimary(true);
                }
            }

            if (registry.containsBeanDefinition(DataSourceConstants.DATA_SOURCE_NAME)) {
                /*
                org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration会自动初始化顺序会在此之前,会优先将Hikari注册为数据源,导致组件默认数据源无法加载。
                 目前没有好的方式将Hikari加载方式去除,,并且由于要加载apollo配置,注册dataSource的生命周期无法提前,这里把Hikari的BeanDefinition删除。
                 */
                BeanDefinition bd = registry.getBeanDefinition(DataSourceConstants.DATA_SOURCE_NAME);
                if (bd.toString().contains("Hikari")) {
                    registry.removeBeanDefinition(DataSourceConstants.DATA_SOURCE_NAME);

                    if (registry.containsBeanDefinition("scopedTarget.dataSource")) {
                        registry.removeBeanDefinition("scopedTarget.dataSource");
                    }
                }
            }

            if (dynamicDataSource) {

                /*default datasource should be configured if use dynamic datasource.*/
                String defaultDynamicDataSource = environment.getProperty(SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_DYNAMIC_DEFAULT,
                    String.class, primaryDataSource);
                Asserts.isTrue(Strings.isNotEmpty(defaultDynamicDataSource),
                    String.format("Property '%s' should be configured!!!", SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_DYNAMIC_DEFAULT));

                if (!allDsNames.contains(defaultDynamicDataSource)) {
                    /*主数据源名称在配置数据源名称中不存在。*/
                    throw new DataSourceSQLException(String.format("The absent default dynamic data source pool %s in the given data sources, please check.", defaultDynamicDataSource));
                }

                String dataSourceFactoryBeanName = primaryDataSource + DynamicDataSourceFactory.class.getSimpleName();
                BeanDefinitionBuilder factoryBuilder =
                    BeanDefinitionBuilder.genericBeanDefinition(DynamicDataSourceFactory.class);
                factoryBuilder.addConstructorArgValue(dependencyRoots);
                factoryBuilder.addConstructorArgValue(defaultDynamicDataSource);
                registry.registerBeanDefinition(dataSourceFactoryBeanName, factoryBuilder.getBeanDefinition());

                BeanDefinition bd = new GenericBeanDefinition();
                bd.setFactoryBeanName(dataSourceFactoryBeanName);
                bd.setFactoryMethodName("getDataSource");
                registry.registerBeanDefinition(DataSourceConstants.DATA_SOURCE_NAME, bd);

            } else {
                /*如果只有一个,则默认为DataSourceConstants.DATA_SOURCE_NAME。*/
                if (dependencyRoots.size() == 1) {

                    if (!registry.containsBeanDefinition(DataSourceConstants.DATA_SOURCE_NAME)) {
                        for (Entry entry : dependencyRoots.entrySet()) {
                            String dataSourceFactoryBeanName =
                                entry.getKey() + DefaultDataSourceFactory.class.getSimpleName();
                            BeanDefinitionBuilder factoryBuilder =
                                BeanDefinitionBuilder.genericBeanDefinition(DefaultDataSourceFactory.class);
                            factoryBuilder.addConstructorArgValue(entry.getKey());
                            registry.registerBeanDefinition(dataSourceFactoryBeanName,
                                factoryBuilder.getBeanDefinition());

                            BeanDefinition bd = new GenericBeanDefinition();
                            bd.setFactoryBeanName(dataSourceFactoryBeanName);
                            bd.setFactoryMethodName("getDataSource");
                            registry.registerBeanDefinition(DataSourceConstants.DATA_SOURCE_NAME, bd);
                        }
                    }
                } else if (Strings.isNotEmpty(primaryDataSource)) {

                    String dataSourceFactoryBeanName =
                        primaryDataSource + DefaultDataSourceFactory.class.getSimpleName();
                    BeanDefinitionBuilder factoryBuilder =
                        BeanDefinitionBuilder.genericBeanDefinition(DefaultDataSourceFactory.class);
                    factoryBuilder.addConstructorArgValue(primaryDataSource);
                    registry.registerBeanDefinition(dataSourceFactoryBeanName, factoryBuilder.getBeanDefinition());

                    BeanDefinition bd = new GenericBeanDefinition();
                    bd.setFactoryBeanName(dataSourceFactoryBeanName);
                    bd.setFactoryMethodName("getDataSource");
                    registry.registerBeanDefinition(DataSourceConstants.DATA_SOURCE_NAME, bd);
                }
            }
        }

        private void rectifyDependencyRoots(Entry rule,
            final Map dependencyRoots) {
            if (rule.getValue().getSingle() != null) {
                dependencyRoots.remove(rule.getValue().getSingle().getDataSourceRef());
            }

            if (rule.getValue().getMasterSlave() != null) {
                dependencyRoots.remove(rule.getValue().getMasterSlave().getMasterDataSourceName());
                rule.getValue().getMasterSlave().getSlaveDataSourceNames()
                    .forEach(slaveDataSource -> dependencyRoots.remove(slaveDataSource));
            }

            if (rule.getValue().getSharding() != null) {
                if (rule.getValue().getSharding().getMasterSlaveRules() != null) {
                    for (Entry entry : rule.getValue().getSharding()
                        .getMasterSlaveRules().entrySet()) {
                        dependencyRoots.remove(entry.getValue().getMasterDataSourceName());
                        entry.getValue().getSlaveDataSourceNames()
                            .forEach(slaveDataSource -> dependencyRoots.remove(slaveDataSource));
                    }
                }
            }
        }

        @Override
        public int getOrder() {
            return Ordered.LOWEST_PRECEDENCE;
        }

    }

    /**
     * DruidDataSource 的 Bean 处理器,将各数据源的自定义配置绑定到 Bean。
     *
     */
    static class DataSourceBeanPostProcessor implements EnvironmentAware, BeanPostProcessor, Ordered {

        private Environment environment;

        public DataSourceBeanPostProcessor() {
            super();
        }

        @Override
        public void setEnvironment(Environment environment) {
            this.environment = environment;
        }

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            boolean dataSourceEnabled = environment.getProperty(SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_ENABLED, boolean.class, false);
            if (!dataSourceEnabled) {
                return bean;
            }

            if (bean instanceof DruidDataSourceWrapper) {
                /*设置 Druid 名称。*/
                com.alibaba.druid.pool.DruidDataSource ds = (com.alibaba.druid.pool.DruidDataSource)bean;
                ds.setName(beanName);

                Map dataSources = DataSourceUtil.getDruidDataSourcePoolBindings(environment);
                if (!dataSources.isEmpty() && dataSources.containsKey(DataSourceUtil.parseDataSourceKey(beanName))) {
                    Binder.get(environment).bind(
                        String.format("%s.%s", SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_DRUID_POOL_PREFIX, DataSourceUtil.parseDataSourceKey(beanName)),
                        Bindable.ofInstance(ds));
                }
                LOGGER.info("ConfigDataSource: {}, url={}", beanName, ds.getUrl());
            } else if (bean instanceof HikariCPDataSourceWrapper) {
                com.zaxxer.hikari.HikariDataSource ds = (com.zaxxer.hikari.HikariDataSource)bean;
                ds.setPoolName(beanName);
                /*规则检测。*/
                ds.validate();

                Map dataSources = DataSourceUtil.getHikariDataSourcePoolBindings(environment);
                if (!dataSources.isEmpty() && dataSources.containsKey(DataSourceUtil.parseDataSourceKey(beanName))) {
                    Binder.get(environment).bind(
                        String.format("%s.%s", SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_HIKARI_POOL_PREFIX, DataSourceUtil.parseDataSourceKey(beanName)),
                        Bindable.ofInstance(ds));
                }
            } else if (bean instanceof BeeDataSourceWrapper) {
                cn.beecp.BeeDataSource ds = (cn.beecp.BeeDataSource)bean;
                ds.setPoolName(beanName);
                try {
                    ds.check();
                    Map dataSources = DataSourceUtil.getDruidDataSourcePoolBindings(environment);
                    if (!dataSources.isEmpty() && dataSources.containsKey(DataSourceUtil.parseDataSourceKey(beanName))) {
                        Binder.get(environment).bind(
                            String.format("%s.%s", SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_BEE_POOL_PREFIX, DataSourceUtil.parseDataSourceKey(beanName)),
                            Bindable.ofInstance(ds));
                    }
                    LOGGER.info("ConfigDataSource: {}, url={}", beanName, ds.getUrl());
                } catch (SQLException e) {
                    LOGGER.error("ConfigDataSource error : {}, url={}, caused by {}", beanName, ds.getUrl(), e);
                }
            } else if (bean instanceof BasicDataSourceWrapper) {
                org.apache.commons.dbcp2.BasicDataSource ds = (org.apache.commons.dbcp2.BasicDataSource)bean;
                Map dataSources = DataSourceUtil.getDbcp2DataSourcePoolBindings(environment);
                if (!dataSources.isEmpty() && dataSources.containsKey(DataSourceUtil.parseDataSourceKey(beanName))) {
                    Binder.get(environment).bind(
                        String.format("%s.%s", SystemPropertiesConstants.Zodiac.SPRING_DATASOURCE_DBCP2_POOL_PREFIX, DataSourceUtil.parseDataSourceKey(beanName)),
                        Bindable.ofInstance(ds));
                }
                LOGGER.info("ConfigDataSource: {}, url={}", beanName, ds.getUrl());
            }

            return bean;
        }

        @Override
        public int getOrder() {
            return Ordered.HIGHEST_PRECEDENCE;
        }
    }

    class DataSourceInitializerPostProcessor implements BeanPostProcessor, Ordered {

        //@Autowired
        private BeanFactory beanFactory;

        DataSourceInitializerPostProcessor(BeanFactory beanFactory) {
            this.beanFactory = beanFactory;
        }

        @Override
        public int getOrder() {
            return Ordered.HIGHEST_PRECEDENCE;
        }

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy