通过在mapper接口上添加自定数据源注解@DataSource来制定数据源
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.9.7</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-aop</artifactId>
- <version>1.5.9.RELEASE</version>
- </dependency>
- import org.linlinjava.litemall.db.datasources.DynamicDataSourceConfig;
- import org.mybatis.spring.annotation.MapperScan;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
- import org.springframework.context.annotation.EnableAspectJAutoProxy;
- import org.springframework.context.annotation.Import;
- import org.springframework.scheduling.annotation.EnableScheduling;
- import org.springframework.transaction.annotation.EnableTransactionManagement;
-
- @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
- @MapperScan("org.linlinjava.litemall.db.dao")
- @EnableTransactionManagement
- @EnableAspectJAutoProxy(proxyTargetClass = true)
- @EnableScheduling
- @Import({DynamicDataSourceConfig.class})
- public class Application {
-
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
-
- }
-
- import java.lang.annotation.*;
-
- /**
- * 多数据源注解
- *
- */
- @Target({ElementType.METHOD, ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface DataSource {
- String name() default "";
- }
- /**
- * 增加多数据源,在此配置
- *
- */
- public interface DataSourceNames {
- String LITEMALL = "mall";
-
- String ZOOM = "zoom";
-
- }
-
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
-
- import javax.sql.DataSource;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 动态数据源
- *
- */
- public class DynamicDataSource extends AbstractRoutingDataSource {
- private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
-
- public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
- super.setDefaultTargetDataSource(defaultTargetDataSource);
- super.setTargetDataSources(new HashMap<>(targetDataSources));
- super.afterPropertiesSet();
- }
-
- @Override
- protected Object determineCurrentLookupKey() {
- return getDataSource();
- }
-
- public static void setDataSource(String dataSource) {
- contextHolder.set(dataSource);
- }
-
- public static String getDataSource() {
- return contextHolder.get();
- }
-
- public static void clearDataSource() {
- contextHolder.remove();
- }
-
- }
-
- import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Primary;
- import org.springframework.core.Ordered;
- import org.springframework.stereotype.Component;
-
-
- import javax.sql.DataSource;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 配置多数据源
- *
- */
- @Configuration
- public class DynamicDataSourceConfig {
-
- @Bean
- @ConfigurationProperties("spring.datasource.druid.mall")
- public DataSource liteMallDataSource() {
- return DruidDataSourceBuilder.create().build();
- }
-
- @Bean
- @ConfigurationProperties("spring.datasource.druid.zoom")
- public DataSource zoomDataSource() {
- return DruidDataSourceBuilder.create().build();
- }
-
- @Bean
- @Primary
- public DynamicDataSource dataSource(DataSource liteMallDataSource, DataSource zoomDataSource) {
- Map<String, DataSource> targetDataSources = new HashMap<>();
- targetDataSources.put(DataSourceNames.LITEMALL, liteMallDataSource);
- targetDataSources.put(DataSourceNames.ZOOM, zoomDataSource);
- return new DynamicDataSource(liteMallDataSource, targetDataSources);
- }
-
- @Aspect
- @Component
- class DataSourceAspect implements Ordered {
- protected Logger logger = LoggerFactory.getLogger(getClass());
-
- public DataSourceAspect() {
- System.out.println(0);
- }
-
- @Pointcut("@within(org.linlinjava.litemall.db.datasources.annotation.DataSource)")
- public void dataSourcePointCut() {
- System.out.println(0);
- }
-
- @Around("dataSourcePointCut()")
- public Object around(ProceedingJoinPoint point) throws Throwable {
-
- org.linlinjava.litemall.db.datasources.annotation.DataSource ds = null;
-
- Class clazz = point.getTarget().getClass();
- ds = (org.linlinjava.litemall.db.datasources.annotation.DataSource) clazz.getAnnotation(org.linlinjava.litemall.db.datasources.annotation.DataSource.class);
-
- if (ds == null) {
- MethodSignature signature = (MethodSignature) point.getSignature();
- Method method = signature.getMethod();
- ds = method.getAnnotation(org.linlinjava.litemall.db.datasources.annotation.DataSource.class);
- }
-
- if (ds == null) {
- DynamicDataSource.setDataSource(DataSourceNames.LITEMALL);
- logger.debug("set datasource is " + DataSourceNames.LITEMALL);
- } else {
- DynamicDataSource.setDataSource(ds.name());
- logger.debug("set datasource is " + ds.name());
- }
-
- try {
- return point.proceed();
- } finally {
- DynamicDataSource.clearDataSource();
- logger.debug("clean datasource");
- }
- }
-
- @Override
- public int getOrder() {
- return 1;
- }
- }
-
- }
- spring:
- datasource:
- type: com.alibaba.druid.pool.DruidDataSource
- druid:
- zoom: #数据源2
- url: xxxxxx/zoom?useUnicode=true&characterEncoding=utf8&useSSL=false
- driver-class-name: com.mysql.cj.jdbc.Driver
- username: 0000
- password: 00000
- filter:
- slf4j:
- enabled: true
- mall:
- url: jdbc:xxxxxx/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=false
- driver-class-name: com.mysql.cj.jdbc.Driver
- username: 00000
- password: 00000
- initial-size: 10
- max-active: 50
- min-idle: 10
- max-wait: 60000
- pool-prepared-statements: true
- max-pool-prepared-statement-per-connection-size: 20
- validation-query: SELECT 1 FROM DUAL
- test-on-borrow: false
- test-on-return: false
- test-while-idle: true
- time-between-eviction-runs-millis: 60000
- webStatFilter:
- enabled: true
- statViewServlet:
- enabled: false
- filter:
- stat:
- enabled: false
-
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.linlinjava.litemall.db.dao.StatMapper;
- import org.linlinjava.litemall.db.dao.ZoomMapper;
- import org.linlinjava.litemall.db.datasources.DynamicDataSourceConfig;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
- import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.context.annotation.Import;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- import org.springframework.test.context.junit4.SpringRunner;
- import org.springframework.test.context.web.WebAppConfiguration;
-
- import javax.annotation.Resource;
-
- @WebAppConfiguration
- @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
- @RunWith(SpringRunner.class)
- @SpringBootTest
- @Import({DynamicDataSourceConfig.class})
- public class DbTest {
-
- @Autowired
- private ZoomMapper zoomMapper;
-
- @Test
- public void test() {
- System.out.println(zoomMapper.queryName());
- }
-
- }
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
zoomMapperService (field org.linlinjava.litemall.db.dao.ZoomMapper org.linlinjava.litemall.db.dao.impl.ZoomMapperService.zoomMapper)
↓
zoomMapper defined in file [F:\workcode\litemall\litemall-db\target\classes\org\linlinjava\litemall\db\dao\ZoomMapper.class]
↓
sqlSessionFactory defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]
┌─────┐
| dataSource defined in class path resource [org/linlinjava/litemall/db/datasources/DynamicDataSourceConfig.class]
↑ ↓
| firstDataSource defined in class path resource [org/linlinjava/litemall/db/datasources/DynamicDataSourceConfig.class]
↑ ↓
| org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker
循环依赖问题
2yaml配置问题
Caused by: org.yaml.snakeyaml.parser.ParserException: while parsing a block mapping
in 'reader', line 9, column 5:
type: com.alibaba.druid.pool.Dru ...
^
expected <block end>, but found '<block mapping start>'
in 'reader', line 19, column 7:
mall:
^at org.yaml.snakeyaml.parser.ParserImpl$ParseBlockMappingKey.produce(ParserImpl.java:572)
at org.yaml.snakeyaml.parser.ParserImpl.peekEvent(ParserImpl.java:158)
at org.yaml.snakeyaml.parser.ParserImpl.checkEvent(ParserImpl.java:148)
at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:214)
at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144)
at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:236)
at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:227)
at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:215)
at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144)
at org.yaml.snakeyaml.composer.Composer.composeValueNode(Composer.java:236)
at org.yaml.snakeyaml.composer.Composer.composeMappingChildren(Composer.java:227)
at org.yaml.snakeyaml.composer.Composer.composeMappingNode(Composer.java:215)
at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:144)
at org.yaml.snakeyaml.composer.Composer.getNode(Composer.java:85)
at org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:123)
at org.yaml.snakeyaml.Yaml$1.next(Yaml.java:547)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:160)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:134)
at org.springframework.boot.env.OriginTrackedYamlLoader.load(OriginTrackedYamlLoader.java:75)
at org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:50)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.loadDocuments(ConfigFileApplicationListener.java:574)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:528)
... 48 common frames omitted