亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JSP > 正文

Spring AOP 動態多數據源的實例詳解

2024-09-05 00:23:21
字體:
來源:轉載
供稿:網友

 Spring AOP 動態多數據源的實例詳解

當項目中使用到讀寫分離的時候,我們就會遇到多數據源的問題。多數據源讓人最頭痛的,不是配置多個數據源,而是如何能靈活動態的切換數據源。例如在一個spring和Mybatis的框架的項目中,我們在spring配置中往往是配置一個dataSource來連接數據庫,然后綁定給sessionFactory,在dao層代碼中再指定sessionFactory來進行數據庫操作。

 Spring,AOP,動態多數據源,詳解

正如上圖所示,每一塊都是指定綁死的,如果是多個數據源,也只能是下圖中那種方式。

Spring,AOP,動態多數據源,詳解

可看出在Dao層代碼中寫死了兩個SessionFactory,這樣日后如果再多一個數據源,還要改代碼添加一個SessionFactory,顯然這并不符合開閉原則。

那么正確的做法應該是:

Spring,AOP,動態多數據源,詳解

具體代碼與配置如下:

1、applicationContext-mgr.xml

<?xml version="1.0" encoding="utf-8" ?><beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xmlns:aop="http://www.springframework.org/schema/aop"  xmlns:context="http://www.springframework.org/schema/context"   xmlns:tx="http://www.springframework.org/schema/tx"  xmlns:p="http://www.springframework.org/schema/p"  xsi:schemaLocation="http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  <!-- use annotation -->  <context:annotation-config />    <context:component-scan base-package="com.carl.o2o.**.mgr">  </context:component-scan>  <!-- master -->  <bean id="master" class="com.mchange.v2.c3p0.ComboPooledDataSource">    <property name="driverClass" value="${driverClassName_master}"/>    <property name="user" value="${username_master}"/>    <property name="password" value="${password_master}"/>    <property name="jdbcUrl" value="${url_master}?Unicode=true&characterEncoding=UTF-8&allowMultiQueries=true"/>    <property name="maxPoolSize" value="150"/>     <property name="minPoolSize" value="10"/>     <property name="initialPoolSize" value="20"/>     <property name="maxIdleTime" value="3600"/>     <property name="acquireIncrement" value="10"/>     <property name="idleConnectionTestPeriod" value="1800"/>    </bean>  <!-- slave -->  <bean id="slave" class="com.mchange.v2.c3p0.ComboPooledDataSource">    <property name="driverClass" value="${driverClassName_slave}"/>    <property name="user" value="${username_slave}"/>    <property name="password" value="${password_slave}"/>    <property name="jdbcUrl" value="${url_slave}?Unicode=true&characterEncoding=UTF-8"/>    <property name="maxPoolSize" value="150"/>     <property name="minPoolSize" value="10"/>     <property name="initialPoolSize" value="20"/>     <property name="maxIdleTime" value="3600"/>     <property name="acquireIncrement" value="10"/>     <property name="idleConnectionTestPeriod" value="1800"/>    </bean>  <!-- spring 動態數據源 -->  <bean id="dynamicDataSource" class="com.carl.dbUtil.DynamicDataSource">    <property name="targetDataSources">       <map key-type="java.lang.String">         <entry key="slave" value-ref="slave" />       </map>     </property>     <property name="defaultTargetDataSource" ref="master" />     </bean>   <!-- mybatis mapper config -->  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">    <property name="dataSource" ref="dynamicDataSource"/>    <property name="configLocation" value="classpath:o2o_mybatis_config.xml"/>    <property name="mapperLocations" >      <list>        <value>classpath:sqlMap/*.xml</value>        <value>classpath*:/com/carl/o2o/**/*.xml</value>      </list>    </property>  </bean>  <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">    <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>  </bean>  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">    <property name="basePackage" value="com.carl.o2o.**.mgr.dao" />  </bean>  <!-- 多數據源 aop -->  <bean id="DataSourceAspect" class="com.carl.dbUtil.DataSourceAspect" />  <aop:config>     <aop:advisor pointcut="execution(* com.carl.o2o.mgr.*.*(..))" advice-ref="DataSourceAspect" />  </aop:config>   <!-- 事務 -->  <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">      <property name="dataSource" ref="dynamicDataSource"></property>  </bean> </beans>

2、DynamicDataSource

DynamicDataSource使用Spring中的代碼結合AOP實現多數據源切換.

public class DynamicDataSource extends AbstractRoutingDataSource {  public DynamicDataSource() {  }  protected Object determineCurrentLookupKey() {    return DBContextHolder.getDbType();  }  public Logger getParentLogger() {    return null;  }}

3、DBContextHolder

DynamicDataSource的輔助類,用于實際的切換多數據源。

public class DBContextHolder {  private static ThreadLocal<String> contextHolder = new ThreadLocal();  public static String MASTER = "master";  public static String SLAVE = "slave";  public DBContextHolder() {  }  public static String getDbType() {    String db = (String)contextHolder.get();    if(db == null) {      db = MASTER;    }    return db;  }  public static void setDbType(String str) {    contextHolder.set(str);  }  public static void setMaster() {    contextHolder.set(MASTER);  }  public static void setSlave() {    contextHolder.set(SLAVE);  }  public static void clearDBType() {    contextHolder.remove();  }}

4、DataSourceAspect

多數據源AOP切面編程實現。

public class DataSourceAspect implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {  private static final Logger log = LogManager.getLogger(DataSourceAspect.class);  public DataSourceAspect() {  }  public void before(Method m, Object[] args, Object target) throws Throwable {    try {      if(m != null) {        if((m.getName().startsWith("list") || m.getName().startsWith("select") || m.getName().startsWith("get")         || m.getName().startsWith("count")) && !m.getName().contains("FromMaster")) {          DBContextHolder.setDbType("slave");        } else {          DBContextHolder.setDbType("master");        }      }    } catch (Exception var5) {      log.error("data source aspect error.", var5);    }  }  public void after(JoinPoint point) {    log.info("clear db type after method.current id {}", new Object[]{Long.valueOf(Thread.currentThread().getId())});    DBContextHolder.clearDBType();  }  public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {  }  public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {    log.info("current db type {} when exception", new Object[]{DBContextHolder.getDbType()});    DBContextHolder.setDbType("master");  }}

以上就是 Spring AOP 動態多數據源的實例詳解,如有疑問請留言或者到本站社區交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


注:相關教程知識閱讀請移步到JSP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情2020午夜免费观看| 日韩女在线观看| 亚洲欧美日韩天堂一区二区| 在线观看欧美www| 国产一区二区三区毛片| 日韩在线视频线视频免费网站| 成人亚洲综合色就1024| 中文字幕综合在线| 色妞欧美日韩在线| 亚洲美女视频网| 国产精品视频最多的网站| 亚洲www永久成人夜色| 日日噜噜噜夜夜爽亚洲精品| 4438全国成人免费| 亚洲第一福利视频| 久久天天躁狠狠躁夜夜躁2014| 亚洲欧美激情视频| 欧美国产第二页| 亚洲欧洲美洲在线综合| 伦伦影院午夜日韩欧美限制| 亚洲精品久久久久久久久久久久久| 欧美亚洲国产日韩2020| 国产精品久久二区| 亚洲国产日韩欧美在线动漫| 欧美日韩亚洲精品一区二区三区| 91精品视频在线看| 国产精品女主播| 欧美激情手机在线视频| 精品国产精品自拍| 国产免费一区二区三区在线能观看| 亚洲国产另类 国产精品国产免费| 国产精品自拍偷拍视频| 8090理伦午夜在线电影| 激情成人在线视频| 欧美二区在线播放| 成人中文字幕+乱码+中文字幕| 国产成人福利网站| 91九色蝌蚪国产| 国产精品成人在线| 中文字幕国产精品久久| 国产在线精品成人一区二区三区| 国产日韩综合一区二区性色av| 2019亚洲日韩新视频| 亚洲欧美日韩中文在线| 在线日韩日本国产亚洲| 久久夜色撩人精品| 欧日韩在线观看| 国产成人福利夜色影视| 久久91精品国产91久久久| 伊是香蕉大人久久| 亚洲第一色在线| 热99精品只有里视频精品| 亚洲欧美日韩区| 国产性猛交xxxx免费看久久| 日韩精品视频中文在线观看| 欧美精品激情在线| 欧美日韩性生活视频| 日韩专区中文字幕| 欧美理论电影在线观看| 亚洲精品有码在线| 成人有码在线播放| 国产精品福利在线观看| 欧美精品亚州精品| 国产精品日韩精品| 日韩精品免费综合视频在线播放| 久久免费成人精品视频| 国产精品xxxxx| 久久九九全国免费精品观看| 欧美视频在线看| 国内精品久久久久久中文字幕| 亚洲美女动态图120秒| 欧美精品性视频| 综合激情国产一区| 在线看国产精品| 伊人久久大香线蕉av一区二区| 欧美日韩综合视频网址| 3344国产精品免费看| 欧美激情手机在线视频| 日韩电影大片中文字幕| 亚洲最大av网站| 国产精品午夜国产小视频| 成人a在线观看| 夜夜狂射影院欧美极品| 国产精品无码专区在线观看| 久久这里只有精品视频首页| 成人黄色免费在线观看| 亚洲精品成人久久| 91九色国产社区在线观看| 欧美性xxxx极品高清hd直播| 成人网页在线免费观看| 日本视频久久久| 色狠狠av一区二区三区香蕉蜜桃| 日韩在线观看免费| 亚洲欧美日韩成人| 色偷偷噜噜噜亚洲男人| 欧美在线观看日本一区| 97国产成人精品视频| 色偷偷88888欧美精品久久久| 91成人国产在线观看| 国产日韩视频在线观看| 国内精品400部情侣激情| 日韩电影中文字幕一区| 国产精品av免费在线观看| 欧美一级bbbbb性bbbb喷潮片| 久久影院模特热| 欧美日韩国产精品一区二区不卡中文| 国产精品v片在线观看不卡| 国产综合在线看| 色偷偷av一区二区三区| 亚洲999一在线观看www| 久久视频国产精品免费视频在线| 亚洲天堂av电影| 久久久久久久影视| 国产精品免费看久久久香蕉| 日韩国产激情在线| 亚洲а∨天堂久久精品9966| 亚洲一区亚洲二区| 91高清免费视频| 亚洲人精选亚洲人成在线| 正在播放欧美一区| 国产午夜精品视频免费不卡69堂| 中文字幕日韩精品在线观看| 欧美激情区在线播放| 亚洲欧美999| 日韩亚洲综合在线| 国产日韩精品在线| 亚洲一区二区久久久久久久| 日本在线精品视频| 尤物九九久久国产精品的分类| 在线性视频日韩欧美| 欧美日韩精品在线播放| 国产精品稀缺呦系列在线| 亚洲欧美福利视频| 九九精品在线观看| 国内免费久久久久久久久久久| 日韩不卡中文字幕| 中文字幕精品—区二区| 国产91热爆ts人妖在线| 国产男人精品视频| 久久99热精品这里久久精品| 黑人巨大精品欧美一区二区一视频| 国产精品18久久久久久首页狼| 性日韩欧美在线视频| 亚洲国产精品嫩草影院久久| 国产精品一区久久久| 欧美激情日韩图片| 伊人男人综合视频网| 亚洲免费视频一区二区| 在线观看欧美日韩国产| 精品亚洲一区二区三区在线播放| 97在线视频精品| 日韩成人av一区| 2020久久国产精品| 亚洲图片欧洲图片av| 亚洲二区在线播放视频| 国产成人福利视频| 国产精品亚发布| 国产一区二区动漫| 欧美大全免费观看电视剧大泉洋| 国产va免费精品高清在线| 国产女人精品视频| 久久天天躁狠狠躁夜夜躁2014| 午夜精品久久久久久久99黑人| 日韩视频中文字幕|