springboot项目,之前有mysql数据源,现在又新增了clickhouse数据源,于是
新增了一个clickhouseDatasource的配置bean,如下:
@Beanpublic DataSource dataSource() throws PropertyVetoException {HikariConfig config = new HikariConfig();String jdbcUrl = ConfigCentre.getString(ConfigConst.EC_MYSQL_URL);if (StringUtils.isBlank(jdbcUrl)) {return null;}String userName = ConfigCentre.getString(ConfigConst.EC_MYSQL_USERNAME);String password = ConfigCentre.getString(ConfigConst.EC_MYSQL_PASSWORD);config.setJdbcUrl(jdbcUrl);config.setUsername(userName);config.setPassword(password);config.addDataSourceProperty("cachePrepStmts", "true");config.addDataSourceProperty("prepStmtCacheSize", "250");config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");HikariDataSource dataSource = new HikariDataSource(config);return dataSource;}@Beanpublic ClickHouseDataSource getClickHouseDataSource(){ClickHouseProperties properties = new ClickHouseProperties();properties.setDataTransferTimeout(5*60*1000);properties.setMaxExecutionTime(5*60*1000);properties.setUseTimeZone("UTC");properties.setUseServerTimeZone(false);ClickHouseDataSource clickHouseDataSource = new ClickHouseDataSource(CLICKHOUSEFORADRESPONSEURL, properties);return clickHouseDataSource;}
用这个bean的时候:
@@Autowiredprivate ClickHouseDataSource clickHouseDataSource;
但是这样就报错了,如下:
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getClickHouseDataSource' defined in com.yeahmobi.dsp.DBBeans:
Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializer':
Invocation of init method failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2: dataSource,getClickHouseDataSource
主要提示在DataSource … but but found 2:dataSource,getClickHouseDataSource
最后发现,是因为Spring认为这两个bean是同一类型的bean
看ClickHouseDataSource这个类的源码:
public class ClickHouseDataSource implements DataSource{...
}
看上面那个DataSource返回的真正实体类:HikariDataSource源码(注:Hikari连接池,号称是java平台最快的,替换druid)
public class HikariDataSource extends HikariConfig implements DataSource, Closeable {...
}
发现ClickHouseDataSource也是实现了DataSource类,而上面那个HikariDataSource也是实现了HikariDataSource ,所以这也算bean重复了。所以得在Bean定义的时候分别申明。
但由于之前这个DataSource,已经有很多地方在用了,改的时候不方便,所以就采用默认是HikariDataSource,用ClickHouseDataSource的时候,再手动申明的策略。
解决:
原来DataSource的Bean定义上,再加注解@Primary,如下:
@Bean@Primarypublic DataSource dataSource() throws PropertyVetoException {......return dataSource;}
用到ClickhouseDataSource Bean的地方,用@Resource注入,指明name是哪个方法名。
@Resource(name = "getClickHouseDataSource")private ClickHouseDataSource clickHouseDataSource;