1. 首页
  2. IT资讯

Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置

“u003Cpu003E技术博文,及时送达u003Cu002Fpu003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002FRelVn4tG7zucng” img_width=”535″ img_height=”10″ alt=”Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置” inline=”0″u003Eu003Cpu003E来自 | 韩数u003Cu002Fpu003Eu003Cpu003Eu003Cstrong toutiao-origin=”span” class=”highlight-text”u003E链接 | juejin.imu002Fpostu002F5d8u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-4″u003E30u003Cu002Fiu003E944f265da03963bd153u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003Eu003Cstrong toutiao-origin=”span” class=”highlight-text”u003E0、前言u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E随着应用用户数量的增加,相应的并发请求的数量也会跟着不断增加,慢慢地,单个数据库已经没有办法满足我们频繁的数据库操作请求了。u003Cu002Fpu003Eu003Cpu003E在某些场景下,我们可能会需要配置多个数据源,使用多个数据源(例如实现数据库的读写分离)来缓解系统的压力等,同样的,Springboot官方提供了相应的实现来帮助开发者们配置多数据源,一般分为两种方式(目前我所了解到的),分包和AOP。u003Cu002Fpu003Eu003Cpu003E而在Springboot +Mybatis实现多数据源配置中,我们实现了静态多数据源的配置,但是这种方式怎么说呢,在实际的使用中不够灵活,为了解决这个问题,我们可以使用上文提到的第二种方法,即使用AOP面向切面编程的方式配合我们的自定义注解来实现在不同数据源之间动态切换的目的。u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E1、数据库准备u003Cu002Fh1u003Eu003Cpu003E数据库准备仍然和之前的例子相同,具体建表sql语句则不再详细说明,表格如下:u003Cu002Fpu003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002FRfrw5NQAxzPtdy” img_width=”574″ img_height=”154″ alt=”Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置” inline=”0″u003Eu003Cpu003E并分别插入两条记录,为了方便对比,其中testdatasource1为芳年25岁的张三, testdatasource2为芳年u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-4″u003E30u003Cu002Fiu003E岁的李四。u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E2、环境准备u003Cu002Fh1u003Eu003Cpu003E首先新建一个Springboot项目,我这里版本是2.1.7.RELEASE,并在pom文件中引入相关依赖,和上次相比,这次主要额外新增了aop相关的依赖,如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E<dependency>u003Cu002Fcodeu003Eu003Ccodeu003E <groupId>mysql<u002FgroupId>u003Cu002Fcodeu003Eu003Ccodeu003E <artifactId>mysql-connector-java<u002FartifactId>u003Cu002Fcodeu003Eu003Ccodeu003E<u002Fdependency>u003Cu002Fcodeu003Eu003Ccodeu003E<dependency>u003Cu002Fcodeu003Eu003Ccodeu003E <groupId>org.springframework.boot<u002FgroupId>u003Cu002Fcodeu003Eu003Ccodeu003E <artifactId>spring-boot-starter-jdbc<u002FartifactId>u003Cu002Fcodeu003Eu003Ccodeu003E<u002Fdependency>u003Cu002Fcodeu003Eu003Ccodeu003E<dependency>u003Cu002Fcodeu003Eu003Ccodeu003E <groupId>org.springframework<u002FgroupId>u003Cu002Fcodeu003Eu003Ccodeu003E <artifactId>spring-aop<u002FartifactId>u003Cu002Fcodeu003Eu003Ccodeu003E <version>5.1.5.RELEASE<u002Fversion>u003Cu002Fcodeu003Eu003Ccodeu003E<u002Fdependency>u003Cu002Fcodeu003Eu003Ccodeu003E<dependency>u003Cu002Fcodeu003Eu003Ccodeu003E <groupId>junit<u002FgroupId>u003Cu002Fcodeu003Eu003Ccodeu003E <artifactId>junit<u002FartifactId>u003Cu002Fcodeu003Eu003Ccodeu003E<u002Fdependency>u003Cu002Fcodeu003Eu003Ccodeu003E<dependency>u003Cu002Fcodeu003Eu003Ccodeu003E <groupId>org.aspectj<u002FgroupId>u003Cu002Fcodeu003Eu003Ccodeu003E <artifactId>aspectjweaver<u002FartifactId>u003Cu002Fcodeu003Eu003Ccodeu003E <version>1.9.2<u002Fversion>u003Cu002Fcodeu003Eu003Ccodeu003E<u002Fdependency>u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch2 toutiao-origin=”h3″u003Eu003Cstrong toutiao-origin=”span” class=”highlight-text”u003E3、代码部分u003Cu002Fstrongu003Eu003Cu002Fh2u003Eu003Cpu003E首先呢,在我们Springboot的配置文件中配置我们的datasourse,和以往不一样的是,因为我们有两个数据源,所以要指定相关数据库的名称,其中主数据源为primary,次数据源为secondary如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E#配置主数据库u003Cu002Fcodeu003Eu003Ccodeu003Espring.datasource.primary.jdbc-url=jdbc:mysql:u002Fu002Flocau003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-6″u003Elhu003Cu002Fiu003Eost:3u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-4″u003E30u003Cu002Fiu003E6u002Ftestdatasource1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=falseu003Cu002Fcodeu003Eu003Ccodeu003Espring.datasource.primary.username=rootu003Cu002Fcodeu003Eu003Ccodeu003Espring.datasource.primary.password=rootu003Cu002Fcodeu003Eu003Ccodeu003Espring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driveru003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E##配置次数据库u003Cu002Fcodeu003Eu003Ccodeu003Espring.datasource.secondary.jdbc-url=jdbc:mysql:u002Fu002Flocau003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-6″u003Elhu003Cu002Fiu003Eost:3u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-4″u003E30u003Cu002Fiu003E6u002Ftestdatasource2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=falseu003Cu002Fcodeu003Eu003Ccodeu003Espring.datasource.secondary.username=rootu003Cu002Fcodeu003Eu003Ccodeu003Espring.datasource.secondary.password=rootu003Cu002Fcodeu003Eu003Ccodeu003Espring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driveru003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003Espring.u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E.encoding.charset=UTF-8u003Cu002Fcodeu003Eu003Ccodeu003Espring.u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E.encoding.enabled=trueu003Cu002Fcodeu003Eu003Ccodeu003Espring.u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E.encoding.force=trueu003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003E需要我们注意的是,Springboot2.0 在配置数据库连接的时候需要使用jdbc-url,如果只使用url的话会报u003Ccodeu003Eu003Cu002Fcodeu003Eu003Cu002Fpu003Eu003Cblockquote toutiao-origin=”span”u003Eu003Ccodeu003EjdbcUrl is required with driverClassName.u003Cu002Fcodeu003Eu003Cu002Fblockquoteu003E错误。u003Cpu003Eu003Cu002Fpu003Eu003Cpu003E新建一个配置文件,DynamicDataSourceConfig 用来配置我们相关的bean,代码如下u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E@Configurationu003Cu002Fcodeu003Eu003Ccodeu003E@Mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003EerScan(basePackages = “com.u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-6″u003Emzdu003Cu002Fiu003E.multipledatasources.mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer”, sqlSessionFactoryRef = “SqlSessionFactory”) u002Fu002FbasePackages 我们接口文件的地址u003Cu002Fcodeu003Eu003Ccodeu003Epublic class DynamicDataSourceConfig {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F 将这个对象放入Spring容器中u003Cu002Fcodeu003Eu003Ccodeu003E @Bean(name = “PrimaryDataSource”)u003Cu002Fcodeu003Eu003Ccodeu003E u002Fu002F 表示这个数据源是默认数据源u003Cu002Fcodeu003Eu003Ccodeu003E @Primaryu003Cu002Fcodeu003Eu003Ccodeu003E u002Fu002F 读取u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Elication.properties中的配置参数映射成为一个对象u003Cu002Fcodeu003Eu003Ccodeu003E u002Fu002F prefix表示参数的前缀u003Cu002Fcodeu003Eu003Ccodeu003E @ConfigurationProperties(prefix = “spring.datasource.primary”)u003Cu002Fcodeu003Eu003Ccodeu003E public DataSource getDateSource1 {u003Cu002Fcodeu003Eu003Ccodeu003E return DataSourceBuilder.create.build;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003E @Bean(name = “SecondaryDataSource”)u003Cu002Fcodeu003Eu003Ccodeu003E @ConfigurationProperties(prefix = “spring.datasource.secondary”)u003Cu002Fcodeu003Eu003Ccodeu003E public DataSource getDateSource2 {u003Cu002Fcodeu003Eu003Ccodeu003E return DataSourceBuilder.create.build;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003E @Bean(name = “dynamicDataSource”)u003Cu002Fcodeu003Eu003Ccodeu003E public DynamicDataSource DataSource(@Qualifier(“PrimaryDataSource”) DataSource primaryDataSource,u003Cu002Fcodeu003Eu003Ccodeu003E @Qualifier(“SecondaryDataSource”) DataSource secondaryDataSource) {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F这个地方是比较核心的targetDataSource 集合是我们数据库和名字之间的映射u003Cu002Fcodeu003Eu003Ccodeu003E Map<Object, Object> targetDataSource = new HashMap<>;u003Cu002Fcodeu003Eu003Ccodeu003E targetDataSource.put(DataSourceType.DataBaseType.Primary, primaryDataSource);u003Cu002Fcodeu003Eu003Ccodeu003E targetDataSource.put(DataSourceType.DataBaseType.Secondary, secondaryDataSource);u003Cu002Fcodeu003Eu003Ccodeu003E DynamicDataSource dataSource = new DynamicDataSource; u003Cu002Fcodeu003Eu003Ccodeu003E dataSource.setTargetDataSources(targetDataSource);u003Cu002Fcodeu003Eu003Ccodeu003E dataSource.setDefaultTargetDataSource(primaryDataSource);u002Fu002F设置默认对象u003Cu002Fcodeu003Eu003Ccodeu003E return dataSource;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003E @Bean(name = “SqlSessionFactory”)u003Cu002Fcodeu003Eu003Ccodeu003E public SqlSessionFactory SqlSessionFactory(@Qualifier(“dynamicDataSource”) DataSource dynamicDataSource)u003Cu002Fcodeu003Eu003Ccodeu003E throws Exception {u003Cu002Fcodeu003Eu003Ccodeu003E SqlSessionFactoryBean bean = new SqlSessionFactoryBean;u003Cu002Fcodeu003Eu003Ccodeu003E bean.setDataSource(dynamicDataSource);u003Cu002Fcodeu003Eu003Ccodeu003E bean.setMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003EerLocations(u003Cu002Fcodeu003Eu003Ccodeu003E new PathMatchingResourcePatternResolver.getResources(“classpath*:mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eingu002F*u002F*.xml”));u002Fu002F设置我们的xml文件路径u003Cu002Fcodeu003Eu003Ccodeu003E return bean.getObject;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003E而在这所有的配置中,最核心的地方就是DynamicDataSource这个类了,DynamicDataSource是我们自定义的动态切换数据源的类,该类继承了AbstractRoutingDataSource 类并重写了它的determineCurrentLookupKey方法。u003Cu002Fpu003Eu003Cpu003EAbstractRoutingDataSource 类内部维护了一个名为targetDataSources的Map,并提供的setter方法用于设置数据源关键字与数据源的关系,实现类被要求实现其determineCurrentLookupKey方法,由此方法的返回值决定具体从哪个数据源中获取连接。同时AbstractRoutingDataSource类提供了程序运行时动态切换数据源的方法,在dao类或方法上标注需要访问数据源的关键字,路由到指定数据源,获取连接。u003Cu002Fpu003Eu003Cpu003EDynamicDataSource代码如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003Epublic class DynamicDataSource extends AbstractRoutingDataSource {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @Overrideu003Cu002Fcodeu003Eu003Ccodeu003E protected Object determineCurrentLookupKey {u003Cu002Fcodeu003Eu003Ccodeu003E DataSourceType.DataBaseType dataBaseType = DataSourceType.getDataBaseType;u003Cu002Fcodeu003Eu003Ccodeu003E return dataBaseType;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003EDataSourceType类的代码如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003Epublic class DataSourceType {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F内部枚举类,用于选择特定的数据类型u003Cu002Fcodeu003Eu003Ccodeu003E public enum DataBaseType {u003Cu002Fcodeu003Eu003Ccodeu003E Primary, Secondaryu003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F 使用ThreadLocal保证线程安全u003Cu002Fcodeu003Eu003Ccodeu003E private static final ThreadLocal<DataBaseType> TYPE = new ThreadLocal<DataBaseType>;u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F 往当前线程里设置数据源类型u003Cu002Fcodeu003Eu003Ccodeu003E public static void setDataBaseType(DataBaseType dataBaseType) {u003Cu002Fcodeu003Eu003Ccodeu003E if (dataBaseType == ) {u003Cu002Fcodeu003Eu003Ccodeu003E throw new PointerException;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E TYPE.set(dataBaseType);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F 获取数据源类型u003Cu002Fcodeu003Eu003Ccodeu003E public static DataBaseType getDataBaseType {u003Cu002Fcodeu003Eu003Ccodeu003E DataBaseType dataBaseType = TYPE.get == ? DataBaseType.Primary : TYPE.get;u003Cu002Fcodeu003Eu003Ccodeu003E return dataBaseType;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F 清空数据类型u003Cu002Fcodeu003Eu003Ccodeu003E public static void clearDataBaseType {u003Cu002Fcodeu003Eu003Ccodeu003E TYPE.remove;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003E接下来编写我们相关的Mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer和xml文件,代码如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E@Componentu003Cu002Fcodeu003Eu003Ccodeu003E@Mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eeru003Cu002Fcodeu003Eu003Ccodeu003Epublic interface PrimaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E List<User> findAll;u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E@Componentu003Cu002Fcodeu003Eu003Ccodeu003E@Mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eeru003Cu002Fcodeu003Eu003Ccodeu003Epublic interface SecondaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E List<User> findAll;u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E<?xml version=”1.0″ encoding=”UTF-8″ ?>u003Cu002Fcodeu003Eu003Ccodeu003E<!DOCTYPE mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eeru003Cu002Fcodeu003Eu003Ccodeu003E PUBLIC “-u002Fu002Fmybatis.orgu002Fu002FDTD Mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer 3.0u002Fu002FEN”u003Cu002Fcodeu003Eu003Ccodeu003E “u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E:u002Fu002Fmybatis.orgu002Fdtdu002Fmybatis-3-mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer.dtd”>u003Cu002Fcodeu003Eu003Ccodeu003E<mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer namespace=”com.jdkcb.mybatisstuday.mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer.one.PrimaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer”>u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E <select id=”findAll” resultType=”com.jdkcb.mybatisstuday.pojo.User”>u003Cu002Fcodeu003Eu003Ccodeu003E select * from sys_user;u003Cu002Fcodeu003Eu003Ccodeu003E <u002Fselect>u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E<u002Fmu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer>u003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003E<?xml version=”1.0″ encoding=”UTF-8″ ?>u003Cu002Fcodeu003Eu003Ccodeu003E<!DOCTYPE mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eeru003Cu002Fcodeu003Eu003Ccodeu003E PUBLIC “-u002Fu002Fmybatis.orgu002Fu002FDTD Mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer 3.0u002Fu002FEN”u003Cu002Fcodeu003Eu003Ccodeu003E “u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E:u002Fu002Fmybatis.orgu002Fdtdu002Fmybatis-3-mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer.dtd”>u003Cu002Fcodeu003Eu003Ccodeu003E<mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer namespace=”com.jdkcb.mybatisstuday.mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer.two.SecondaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer”>u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E <select id=”findAll” resultType=”com.jdkcb.mybatisstuday.pojo.User”>u003Cu002Fcodeu003Eu003Ccodeu003E select * from sys_user2;u003Cu002Fcodeu003Eu003Ccodeu003E <u002Fselect>u003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003E<u002Fmu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer>u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003E相关接口文件编写好之后,就可以编写我们的aop代码了:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E@Aspectu003Cu002Fcodeu003Eu003Ccodeu003E@Componentu003Cu002Fcodeu003Eu003Ccodeu003Epublic class DataSourceAop {u003Cu002Fcodeu003Eu003Ccodeu003E u002Fu002F在primary方法前执行u003Cu002Fcodeu003Eu003Ccodeu003E @Before(“execution(* com.jdkcb.mybatisstuday.controller.UserController.primary(..))”)u003Cu002Fcodeu003Eu003Ccodeu003E public void setDataSource2test01 {u003Cu002Fcodeu003Eu003Ccodeu003E System.err.println(“Primary业务”);u003Cu002Fcodeu003Eu003Ccodeu003E DataSourceType.setDataBaseType(DataSourceType.DataBaseType.Primary);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E u002Fu002F在secondary方法前执行u003Cu002Fcodeu003Eu003Ccodeu003E @Before(“execution(* com.jdkcb.mybatisstuday.controller.UserController.secondary(..))”)u003Cu002Fcodeu003Eu003Ccodeu003E public void setDataSource2test02 {u003Cu002Fcodeu003Eu003Ccodeu003E System.err.println(“Secondary业务”);u003Cu002Fcodeu003Eu003Ccodeu003E DataSourceType.setDataBaseType(DataSourceType.DataBaseType.Secondary);u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003E编写我们的测试 UserController, 代码如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E@RestControlleru003Cu002Fcodeu003Eu003Ccodeu003Epublic class UserController {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @Autowiredu003Cu002Fcodeu003Eu003Ccodeu003E private PrimaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer primaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer;u003Cu002Fcodeu003Eu003Ccodeu003E @Autowiredu003Cu002Fcodeu003Eu003Ccodeu003E private SecondaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer secondaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer;u003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003E @RequestMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eing(“primary”)u003Cu002Fcodeu003Eu003Ccodeu003E public Object primary{u003Cu002Fcodeu003Eu003Ccodeu003E List<User> list = primaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer.findAll;u003Cu002Fcodeu003Eu003Ccodeu003E return list;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E @RequestMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eing(“secondary”)u003Cu002Fcodeu003Eu003Ccodeu003E public Object secondary{u003Cu002Fcodeu003Eu003Ccodeu003E List<User> list = secondaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer.findAll;u003Cu002Fcodeu003Eu003Ccodeu003E return list;u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E4、测试u003Cu002Fh1u003Eu003Cpu003E启动项目,在浏览器中分别输入u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E:u002Fu002F127.0.0.1:8080u002Fprimary 和u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E:u002Fu002F127.0.0.1:8080u002Fprimary ,结果如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E[{“user_id”:1,”user_name”:”张三”,”user_age”:25}]u003Cu002Fcodeu003Eu003Ccodeu003E[{“user_id”:1,”user_name”:”李四”,”user_age”:u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-4″u003E30u003Cu002Fiu003E}]u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E5、等等u003Cu002Fh1u003Eu003Cpu003E等等,啧啧啧,我看你这不行啊,还不够灵活,几个菜啊,喝成这样,这就算灵活了?u003Cu002Fpu003Eu003Cpu003E那肯定不能的,aop也有aop的好处,比如两个包下的代码分别用两个不同的数据源,就可以直接用aop表达式就可以完成了,但是,如果想本例中方法级别的拦截,就显得优点不太灵活了,这个适合就需要我们的注解上场了。u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E6、配合注解实现u003Cu002Fh1u003Eu003Cpu003E首先自定义我们的注解 @DataSourceu003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003Eu002F**u003Cu002Fcodeu003Eu003Ccodeu003E * 切换数据注解 可以用于类或者方法级别 方法级别优先级 > 类级别u003Cu002Fcodeu003Eu003Ccodeu003E *u002Fu003Cu002Fcodeu003Eu003Ccodeu003E@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})u003Cu002Fcodeu003Eu003Ccodeu003E@Retention(RetentionPolicy.RUNTIME)u003Cu002Fcodeu003Eu003Ccodeu003E@Documentedu003Cu002Fcodeu003Eu003Ccodeu003Epublic @interface DataSource {u003Cu002Fcodeu003Eu003Ccodeu003E String value default “primary”; u002Fu002F该值即key值,默认使用默认数据库u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003E通过使用aop拦截,获取注解的属性value的值。如果value的值并没有在我们DataBaseType里面,则使用我们默认的数据源,如果有的话,则切换为相应的数据源。u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E@Aspectu003Cu002Fcodeu003Eu003Ccodeu003E@Componentu003Cu002Fcodeu003Eu003Ccodeu003Epublic class DynamicDataSourceAspect {u003Cu002Fcodeu003Eu003Ccodeu003E private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @Before(“@annotation(dataSource)”)u002Fu002F拦截我们的注解u003Cu002Fcodeu003Eu003Ccodeu003E public void changeDataSource(JoinPoint point, DataSource dataSource) throws Throwable {u003Cu002Fcodeu003Eu003Ccodeu003E String value = dataSource.value;u003Cu002Fcodeu003Eu003Ccodeu003E if (value.equals(“primary”)){u003Cu002Fcodeu003Eu003Ccodeu003E DataSourceType.setDataBaseType(DataSourceType.DataBaseType.Primary);u003Cu002Fcodeu003Eu003Ccodeu003E }else if (value.equals(“secondary”)){u003Cu002Fcodeu003Eu003Ccodeu003E DataSourceType.setDataBaseType(DataSourceType.DataBaseType.Secondary);u003Cu002Fcodeu003Eu003Ccodeu003E }else {u003Cu002Fcodeu003Eu003Ccodeu003E DataSourceType.setDataBaseType(DataSourceType.DataBaseType.Primary);u002Fu002F默认使用主数据库u003Cu002Fcodeu003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @After(“@annotation(dataSource)”) u002Fu002F清除数据源的配置u003Cu002Fcodeu003Eu003Ccodeu003E public void restoreDataSource(JoinPoint point, DataSource dataSource) {u003Cu002Fcodeu003Eu003Ccodeu003E DataSourceType.clearDataBaseType;u003Cu002Fcodeu003Eu003Cbru003Eu003Cbru003Eu003Ccodeu003E }u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E7、测试u003Cu002Fh1u003Eu003Cpu003E修改我们的mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer,添加我们的自定义的@DataSouse注解,并注解掉我们DataSourceAop类里面的内容。如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E@Componentu003Cu002Fcodeu003Eu003Ccodeu003E@Mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eeru003Cu002Fcodeu003Eu003Ccodeu003Epublic interface PrimaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @DataSourceu003Cu002Fcodeu003Eu003Ccodeu003E List<User> findAll;u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E@Componentu003Cu002Fcodeu003Eu003Ccodeu003E@Mu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eeru003Cu002Fcodeu003Eu003Ccodeu003Epublic interface SecondaryUserMu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-1″u003Eappu003Cu002Fiu003Eer {u003Cu002Fcodeu003Eu003Cbru003Eu003Ccodeu003E @DataSource(“secondary”)u002Fu002F指定数据源为:secondaryu003Cu002Fcodeu003Eu003Ccodeu003E List<User> findAll;u003Cu002Fcodeu003Eu003Ccodeu003E}u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003E启动项目,在浏览器中分别输入u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E:u002Fu002F127.0.0.1:8080u002Fprimary 和u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-3″u003Ehttpu003Cu002Fiu003E:u002Fu002F127.0.0.1:8080u002Fprimary ,结果如下:u003Cu002Fpu003Eu003Cpreu003Eu003Cdivu003Eu003Cpreu003Eu003Ccodeu003E[{“user_id”:1,”user_name”:”张三”,”user_age”:25}]u003Cu002Fcodeu003Eu003Ccodeu003E[{“user_id”:1,”user_name”:”李四”,”user_age”:u003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-4″u003E30u003Cu002Fiu003E}]u003Cu002Fcodeu003Eu003Cu002Fpreu003Eu003Cu002Fdivu003Eu003Cu002Fpreu003Eu003Cpu003E到此,就算真正的大功告成啦。u003Cu002Fpu003Eu003Cpu003Eu003Cu002Fpu003Eu003Ch1 toutiao-origin=”h2″u003E8、源码u003Cu002Fh1u003Eu003Cpu003Egithubu003Ci class=”chrome-extension-mutihighlight chrome-extension-mutihighlight-style-4″u003E.comu003Cu002Fiu003Eu002Fhanshuaikangu002FHanShu-Noteu003Cu002Fpu003E”

原文始发于:Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置

主题测试文章,只做测试使用。发布者:逗乐男神i,转转请注明出处:http://www.cxybcw.com/17872.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code