欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

SpringBoot中AOP方式實(shí)現(xiàn)多數(shù)據(jù)源切換的示例分析-創(chuàng)新互聯(lián)

小編給大家分享一下SpringBoot中AOP方式實(shí)現(xiàn)多數(shù)據(jù)源切換的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

成都創(chuàng)新互聯(lián)公司自2013年起,我們提供高端網(wǎng)站建設(shè)、小程序開發(fā)、電商視覺設(shè)計(jì)、重慶APP開發(fā)公司及網(wǎng)絡(luò)營銷搜索優(yōu)化服務(wù),在傳統(tǒng)互聯(lián)網(wǎng)與移動互聯(lián)網(wǎng)發(fā)展的背景下,我們堅(jiān)守著用標(biāo)準(zhǔn)的設(shè)計(jì)方案與技術(shù)開發(fā)實(shí)力作基礎(chǔ),以企業(yè)及品牌的互聯(lián)網(wǎng)商業(yè)目標(biāo)為核心,為客戶打造具商業(yè)價值與用戶體驗(yàn)的互聯(lián)網(wǎng)+產(chǎn)品。

設(shè)計(jì)總體思路

Spring-Boot+AOP方式實(shí)現(xiàn)多數(shù)據(jù)源切換,繼承AbstractRoutingDataSource實(shí)現(xiàn)數(shù)據(jù)源動態(tài)的獲取,在service層使用注解指定數(shù)據(jù)源。

步驟

一、多數(shù)據(jù)源配置

在application.properties中,我們的配置是這樣的

#主數(shù)據(jù)源
druid.master.url=jdbc:mysql://url/masterdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
druid.master.username=xxx
druid.master.password=123
druid.master.driver-class-name=com.mysql.jdbc.Driver
druid.master.max-wait=5000
druid.master.max-active=100
druid.master.test-on-borrow=true
druid.master.validation-query=SELECT 1

#從數(shù)據(jù)源
druid.slave.url=jdbc:mysql://url/slavedb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
druid.slave.username=xxx
druid.slave.password=123
druid.slave.driver-class-name=com.mysql.jdbc.Driver
druid.slave.max-wait=5000
druid.slave.max-active=100
druid.slave.test-on-borrow=true
druid.slave.validation-query=SELECT 1

讀取配置

<!-- master數(shù)據(jù)源 -->
<bean primary="true" id="masterdb" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
  <!-- 基本屬性 url、user、password -->
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="${druid.master.url}"/>
  <property name="username" value="${druid.master.username}"/>
  <property name="password" value="${druid.master.password}"/>
  <!-- 配置初始化大 -->
  <property name="maxActive" value="${druid.master.max-active}"/>
  <!-- 配置獲取連接等待超時的時間 -->
  <property name="maxWait" value="${druid.master.max-wait}"/>
  <property name="validationQuery" value="${druid.master.validation-query}"/>
  <property name="testOnBorrow" value="${druid.master.test-on-borrow}"/>

</bean>

<!-- slave數(shù)據(jù)源 -->
<bean primary="true" id="slavedb" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
  <!-- 基本屬性 url、user、password -->
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="${druid.slave.url}"/>
  <property name="username" value="${druid.slave.username}"/>
  <property name="password" value="${druid.slave.password}"/>

  <!-- 配置初始化大小、最小、大 -->
  <property name="maxActive" value="${druid.slave.max-active}"/>
  <!-- 配置獲取連接等待超時的時間 -->
  <property name="maxWait" value="${druid.slave.max-wait}"/>
  <property name="validationQuery" value="${druid.slave.validation-query}"/>
  <property name="testOnBorrow" value="${druid.slave.test-on-borrow}"/>
</bean>

<!-- 動態(tài)數(shù)據(jù)源,根據(jù)service接口上的注解來決定取哪個數(shù)據(jù)源 -->
<bean id="dataSource" class="datasource.DynamicDataSource">
  <property name="targetDataSources">
    <map key-type="java.lang.String">
      <entry key="slave" value-ref="slavedb"/>
      <entry key="master" value-ref="masterdb"/>
    </map>
  </property>
  <property name="defaultTargetDataSource" ref="masterdb"/>
</bean>

<!-- Spring JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  <property name="dataSource" ref="dataSource" />
</bean>

<!-- Spring事務(wù)管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource" />
</bean>

<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
  <property name="transactionManager" ref="transactionManager"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="2" />

<!-- depositdbSqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:mapper-xxdb/*Mapper*.xml" />
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="xxdb.mapper"/>
  <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

二、動態(tài)數(shù)據(jù)源

spring為我們提供了AbstractRoutingDataSource,即帶路由的數(shù)據(jù)源。繼承后我們需要實(shí)現(xiàn)它的determineCurrentLookupKey(),該方法用于自定義實(shí)際數(shù)據(jù)源名稱的路由選擇方法,由于我們將信息保存到了ThreadLocal中,所以只需要從中拿出來即可。

public class DynamicDataSource extends AbstractRoutingDataSource {
  private Logger logger = LoggerFactory.getLogger(this.getClass());

  @Override
  protected Object determineCurrentLookupKey() {
    String dataSource = JdbcContextHolder.getDataSource();
    logger.info("數(shù)據(jù)源為{}",dataSource);
    return dataSource;
  }
}

三. 數(shù)據(jù)源動態(tài)切換類

動態(tài)數(shù)據(jù)源切換是基于AOP的,所以我們需要聲明一個AOP切面,并在切面前做數(shù)據(jù)源切換,切面完成后移除數(shù)據(jù)源名稱。

@Aspect
@Order(1)  //設(shè)置AOP執(zhí)行順序(需要在事務(wù)之前,否則事務(wù)只發(fā)生在默認(rèn)庫中)
@Component
public class DataSourceAspect {

  private Logger logger = LoggerFactory.getLogger(this.getClass());
  //切點(diǎn)
  @Pointcut("execution(* com.xxx.service.*.*(..))")
  public void aspect() { }

  @Before("aspect()")
  private void before(JoinPoint point) {
    Object target = point.getTarget();
    String method = point.getSignature().getName();
    Class<?> classz = target.getClass();// 獲取目標(biāo)類
    Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())
        .getMethod().getParameterTypes();
    try {
      Method m = classz.getMethod(method, parameterTypes);
      if (m != null && m.isAnnotationPresent(MyDataSource.class)) {
        MyDataSource data = m.getAnnotation(MyDataSource.class);
        logger.info("method :{},datasource:{}",m.getName() ,data.value().getName());
        JdbcContextHolder.putDataSource(data.value().getName());// 數(shù)據(jù)源放到當(dāng)前線程中
      }
    } catch (Exception e) {
      logger.error("get datasource error ",e);
      //默認(rèn)選擇master
      JdbcContextHolder.putDataSource(DataSourceType.Master.getName());// 數(shù)據(jù)源放到當(dāng)前線程中
    }

  }

  @AfterReturning("aspect()")
  public void after(JoinPoint point) {
    JdbcContextHolder.clearDataSource();
  }
}

四、數(shù)據(jù)源管理類

public class JdbcContextHolder {

  private final static ThreadLocal<String> local = new ThreadLocal<>();

  public static void putDataSource(String name) {
    local.set(name);
  }

  public static String getDataSource() {
    return local.get();
  }

  public static void clearDataSource() {
    local.remove();
  }
}

五、數(shù)據(jù)源注解和枚舉

我們切換數(shù)據(jù)源時,一般都是在調(diào)用具體接口的方法前實(shí)現(xiàn),所以我們定義一個方法注解,當(dāng)AOP檢測到方法上有該注解時,根據(jù)注解中value對應(yīng)的名稱進(jìn)行切換。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyDataSource {

  DataSourceType value();

}
public enum DataSourceType {
  // 主表
  Master("master"),
  // 從表
  Slave("slave");

  private String name;

  private DataSourceType(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

六、切點(diǎn)注解

由于我們的動態(tài)數(shù)據(jù)源配置了默認(rèn)庫,所以如果方法是操作默認(rèn)庫的可以不需要注解,如果要操作非默認(rèn)數(shù)據(jù)源,我們需要在方法上添加@MyDataSource("數(shù)據(jù)源名稱")注解,這樣就可以利用AOP實(shí)現(xiàn)動態(tài)切換了

@Component
public class xxxServiceImpl {
  @Resource
  private XxxMapperExt xxxMapperExt;

  @MyDataSource(value= DataSourceType.Slave)
  public List<Object> getAll(){
    return xxxMapperExt.getAll();
  }
}

看完了這篇文章,相信你對“SpringBoot中AOP方式實(shí)現(xiàn)多數(shù)據(jù)源切換的示例分析”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

網(wǎng)站標(biāo)題:SpringBoot中AOP方式實(shí)現(xiàn)多數(shù)據(jù)源切換的示例分析-創(chuàng)新互聯(lián)
本文網(wǎng)址:http://chinadenli.net/article6/ephig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、軟件開發(fā)、網(wǎng)頁設(shè)計(jì)公司做網(wǎng)站、App設(shè)計(jì)、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)
国产亚洲欧美一区二区| 日韩成人动作片在线观看 | 中文字幕人妻av不卡| 国产成人午夜在线视频| 开心五月激情综合婷婷色| 日本一区二区三区黄色| 亚洲最新中文字幕在线视频| 欧美一区二区三区99| 久久热中文字幕在线视频| 有坂深雪中文字幕亚洲中文| 中文字幕一区二区三区中文| 亚洲天堂精品一区二区| 国产成人在线一区二区三区| 国产精品日本女优在线观看| 爱在午夜降临前在线观看| 熟女少妇一区二区三区蜜桃| 亚洲高清一区二区高清| 色哟哟在线免费一区二区三区| 亚洲国产婷婷六月丁香| 久久亚洲精品中文字幕| 国产精品一区二区日韩新区| 人妻亚洲一区二区三区| 国产不卡的视频在线观看| 国产欧美日韩综合精品二区| 东京热男人的天堂久久综合| 视频一区二区 国产精品| 少妇成人精品一区二区| 欧美激情视频一区二区三区| 免费福利午夜在线观看| 99国产一区在线播放| 日韩精品一区二区毛片| 国产欧美日产久久婷婷| 日本加勒比中文在线观看| 99一级特黄色性生活片| 69久久精品亚洲一区二区| 亚洲伊人久久精品国产| 在线日韩中文字幕一区| 91人妻久久精品一区二区三区| 日本女人亚洲国产性高潮视频| 日本成人三级在线播放| 亚洲一区二区三区三区|