多数据源配置(mysql读写分离)

来源:互联网 发布:二维码追溯系统源码 编辑:程序博客网 时间:2024/06/16 14:58

applicationContext.xml 配置:

<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:cache="http://www.springframework.org/schema/cache"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context   http://www.springframework.org/schema/context/spring-context-4.2.xsd  http://www.springframework.org/schema/tx    http://www.springframework.org/schema/tx/spring-tx-4.2.xsd    http://www.springframework.org/schema/cachehttp://www.springframework.org/schema/cache/spring-cache-4.2.xsd"><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /><property name="ignoreResourceNotFound" value="true" /><property name="locations"><list><!-- 标准配置 --><value>classpath:config/jdbc.properties</value><value>classpath:config/config.properties</value></list></property></bean><!-- (事务管理)transaction manager, use JtaTransactionManager for global tx --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 事务注解驱动,标注@Transactional的类和方法将具有事务性 --><tx:annotation-driven transaction-manager="transactionManager" /><bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /><!-- 创建SqlSessionFactory,同时指定数据源 --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><!--数组类型,用来指定别名的。指定了这个属性后,Mybatis会把这个类型的短名称作为这个类型的别名, 前提是该类上没有标注@Alias注解,否则将使用该注解对应的值作为此种类型的别名。 --><property name="typeAliasesPackage" value="gevek.vr.model" /><!-- 指定mybatis的配置文件信息 --><property name="configLocation" value="classpath:config/mybatis-config.xml" /><property name="mapperLocations" value="classpath:config/mapper/*.xml" /></bean><!-- Mapper接口所在包名,Spring会自动查找其下的Mapper --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="gevek.vr.mapper" /><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /></bean><bean id="readUserDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"><property name="name" value="read" /><property name="driverClassName" value="${readUserDataSource.jdbc.driver}"/><property name="url" value="${readUserDataSource.jdbc.url}"/><property name="username" value="${readUserDataSource.jdbc.username}"/><property name="password" value="${readUserDataSource.jdbc.password}"/><property name="filters" value="stat" /><property name="initialSize" value="5" /><property name="minIdle" value="5" /><property name="maxActive" value="200" /><property name="maxWait" value="150000" /><property name="timeBetweenEvictionRunsMillis" value="60000" /><property name="minEvictableIdleTimeMillis" value="1800000" /><property name="validationQuery" value="SELECT 'x'" /><property name="removeAbandoned" value="true" /><property name="testWhileIdle" value="true" /><property name="testOnBorrow" value="false" /><property name="testOnReturn" value="false" /></bean><bean id="writeUserDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"><property name="name" value="write" /><property name="driverClassName" value="${writeUserDataSource.jdbc.driver}"/><property name="url" value="${writeUserDataSource.jdbc.url}"/><property name="username" value="${writeUserDataSource.jdbc.username}"/><property name="password" value="${writeUserDataSource.jdbc.password}"/><property name="filters" value="stat" /><property name="initialSize" value="2" /><property name="minIdle" value="2" /><property name="maxActive" value="150" /><property name="maxWait" value="150000" /><property name="timeBetweenEvictionRunsMillis" value="60000" /><property name="minEvictableIdleTimeMillis" value="1800000" /><property name="validationQuery" value="SELECT 'x'" /><property name="removeAbandoned" value="true" /><property name="testWhileIdle" value="true" /><property name="testOnBorrow" value="false" /><property name="testOnReturn" value="false" /></bean><!-- 多数据源配置 --><bean id="dataSource"  class="gevek.vr.common.datasource.TradingRoutingDataSource"><property name="targetDataSources"><map key-type="java.lang.String"><entry key="readUserDataSource" value-ref="readUserDataSource"/><entry key="writeUserDataSource" value-ref="writeUserDataSource"/></map></property><!-- common里只定义一个默认数据源--><property name="defaultTargetDataSource" ref="readUserDataSource"/></bean><bean id="dataSourceBeforeAdvice" class="gevek.vr.common.datasource.DataSourceBeforeAdvice"/><bean id="datasourceAfterAdvice" class="gevek.vr.common.datasource.DataSourceAfterAdvice"/><aop:config proxy-target-class="false" expose-proxy="true" ><aop:advisor advice-ref="dataSourceBeforeAdvice" order="100" pointcut="execution(* .aa..*service.*.*(..))"/></aop:config><aop:config proxy-target-class="false" expose-proxy="true"><aop:advisor advice-ref="datasourceAfterAdvice" order="400" pointcut="execution(* aa..*service.*.*(..))" /></aop:config><!-- 使用ehcache缓存 --><bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"><property name="configLocation" value="classpath:config/ehcache.xml"></property></bean><bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"><property name="cacheManager" ref="ehcache"></property></bean><cache:annotation-driven cache-manager="cacheManager" /></beans>


DataSourceBeforeAdvice 和 DataSourceAfterAdvice 在事务注解之前或之后需要做的事:
package aa.datasource;import aa.TradingDataSource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class DataSourceBeforeAdvice implements MethodBeforeAdvice {    private static Logger logger = LoggerFactory.getLogger(DataSourceBeforeAdvice.class);    public void before(Method method, Object[] args, Object target) throws Throwable {        TradingDataSource tds;        tds = target.getClass().getAnnotation(TradingDataSource.class);        if (tds == null) {            tds = method.getAnnotation(TradingDataSource.class);            if (tds == null) {                Method objectMethod = target.getClass().getMethod(method.getName(), method.getParameterTypes());                tds = objectMethod.getAnnotation(TradingDataSource.class);            }        }        if (tds != null) {            logger.debug("Set dataSource [{}] to current {}.", tds.name(), Thread.currentThread());            TradingDataSourceHolder.setThreadDataSource(tds.name());        }    }}


package aa.datasource;import org.springframework.aop.AfterReturningAdvice;import org.springframework.aop.ThrowsAdvice;import java.lang.reflect.Method;public class DataSourceAfterAdvice implements AfterReturningAdvice, ThrowsAdvice {public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {TradingDataSourceHolder.clearThreadDataSource();}public void afterThrowing(Exception ex) {TradingDataSourceHolder.clearThreadDataSource();}}



package gevek.vr.common.common;public interface DataSource {public final static String READ_SOURCE = "readUserDataSource";public final static String WRITE_SOURCE = "writeUserDataSource";}


在默认情况下直接进行使用,因为已经默认使用读库,只有在写库下才需要使用注解进行配置即可:

   @Autowired  UserMapper userMapper;
    @TradingDataSource(name = DataSource.WRITE_SOURCE)    public void abc(User user) {
userMapper.insert(user);
}