spring下mysql读写分离配置,解决争抢DataSource问题

1,此类实现AbstractRoutingDataSource类

/** 

* @ClassName: DynamicDataSource 
* @Description: 动态数据源实现类 
* @author A18ccms a18ccms_gmail_com 
* @date 2016-9-18 上午10:06:56 
*  
*/
public class DynamicDataSource extends AbstractRoutingDataSource{


//返回当前数据源
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSource();
}


}


2,

/** 
* @ClassName: DynamicDataSourceHolder 
* @Description:数据源切换类
* @author yunlin.liu 
* @date 2016-9-18 上午10:02:32 
*  
*/
public class DynamicDataSourceHolder {
@SuppressWarnings("rawtypes")
private static final ThreadLocal contextHolder = new ThreadLocal();

   private static final String DATA_SOURCE_SLAVE = "slave" ;

   @SuppressWarnings("unchecked")
public static void setDataSource(String dataSource) {
       Assert.notNull(dataSource, "dataSource cannot be null");
       contextHolder.set(dataSource);
}

   public static void setMaster(){
       clearDataSource();
}

   public static void setSlave() {
       setDataSource( DATA_SOURCE_SLAVE);
}

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

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


3,利用AOP切换进行数据源切换

@Aspect
@Component
public class DataSourceAdvice implements MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice {

//log4j
private static Logger log = Logger.getLogger(DataSourceAdvice.class);


 //service方法执行之前被调用
public void before(Method method, Object[] args, Object target) throws Throwable {
      log.info("切入点: " + target.getClass().getName() + "类中" + method.getName() + "方法");
      if (method.getName().startsWith("add") || method.getName().startsWith("increase")
        || method.getName().startsWith("decrease") || method.getName().startsWith("update")
        || method.getName().startsWith("immediate") || method.getName().startsWith("edit")
        ) {
          log.info("切换到: master");
          DynamicDataSourceHolder.setMaster();
      } else {
         log.info("切换到: slave");
         DynamicDataSourceHolder.setSlave();
      }
}


// service方法执行完之后被调用
public void afterReturning(Object var1, Method var2, Object[] var3, Object var4) throws Throwable {
DynamicDataSourceHolder.setMaster(); 
}


// 抛出Exception之后被调用
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
DynamicDataSourceHolder.setSlave();
log.info("出现异常,切换到: slave");

}

}


4,配置文件

<!-- 数据源 写-->
<bean id="dataSourceWrite" class="com.alibaba.druid.pool.DruidDataSource"  init-method="init"
destroy-method="close">
<property name="driverClassName" value="${driverW}" />
<property name="url" value="${urlW}" />
<property name="username" value="${usernameW}" />
<property name="password" value="${passwordW}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="1" />
<!-- 连接池最大数量 -->
<property name="maxActive" value="50" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="1" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
</bean>

<!-- 数据源 读-->
<bean id="dataSourceRead" class="com.alibaba.druid.pool.DruidDataSource"  init-method="init"
destroy-method="close">
<property name="driverClassName" value="${driverR}" />
<property name="url" value="${urlR}" />
<property name="username" value="${usernameR}" />
<property name="password" value="${passwordR}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="1" />
<!-- 连接池最大数量 -->
<property name="maxActive" value="50" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="1" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
</bean>

<bean id="dataSource" class="com.wtjr.common.util.DynamicDataSource">
    <property name="targetDataSources">
        <map key-type="java.lang.String">
            <entry key="slave" value-ref="dataSourceRead" />
            <entry key="master" value-ref="dataSourceWrite" />
        </map>
    </property>
    <property name="defaultTargetDataSource" ref="dataSourceWrite" />
</bean>


<!--开启自动代理功能 true使用CGLIB   -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 配置通知和切点 注意这个一定要配置在事务声明(txAdvice)之前 否则就会出现数据源切换出错  -->
<aop:config>
  <aop:advisor pointcut="execution(* com.wtjr.service.impl.*.*(..))" advice-ref="dataSourceAdvice" />
</aop:config>

<!-- 配置事物管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    <property name="dataSource" ref="dataSource"></property>  
</bean> 


  <!--配置事务的传播特性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
<!-- 对增、删、改方法进行事务支持 -->
<tx:method name="add*" propagation="REQUIRED" />
        <tx:method name="increase*" propagation="REQUIRED" />
        <tx:method name="decrease*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED" />
        <tx:method name="immediate*" propagation="REQUIRED" />
        <tx:method name="edit*" propagation="REQUIRED" />
<!-- 对查找方法进行只读事务 -->
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="query*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
          <tx:method name="count*" propagation="SUPPORTS" read-only="true"/>
<!-- 对其它方法进行事务 -->
        <tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>


<!--开启注解式事务扫描 要开启事务的service实现类中 加上@Transactional注解-->
<tx:annotation-driven/>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值