项目中用的的,展示给大家,结构如下
applicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
">
<description>Spring公共配置 </description>
<!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
<context:component-scan base-package="com.test">
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:app.properties</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<!-- MyBatis配置 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="typeAliasesPackage" value="com.test.model" />
<property name="mapperLocations" value="classpath*:/mybatis/*Mapper.xml" />
<property name="dataSource">
<ref bean="dynamicDataSource" />
</property>
</bean>
<!-- 扫描basePackage下所有以@MyBatisRepository标识的 接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.dao.mybatis" />
<!-- <property name="annotationClass" value="jarlun.framework.core.base.mybatis.MyBatisRepository"
/> -->
</bean>
<bean id="dynamicDataSource" class="com.test.holder.DynamicDataSource">
<!-- 通过key-value的形式来关联数据源 -->
<property name="targetDataSources">
<map key-type ="java.lang.String">
<entry value-ref="master" key="master"></entry>
<entry value-ref="slave" key="slave"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="master" />
</bean>
<!-- JSR303 Validator定义 -->
<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册 -->
<!-- 建立视图内拦截器来解决JPA中访问延迟加载属性时产生的无会话异常 LazyInitializationException: could
not initialize proxy no session -->
<!-- 此拦截器会注入到servlet配置中的DefaultAnnotationHandlerMapping中 -->
<bean id="master" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${master.jdbc.driver}" />
<property name="url" value="${master.jdbc.url}" />
<property name="username" value="${master.jdbc.username}" />
<property name="password" value="${master.jdbc.password}" />
<!-- Connection Pooling Info -->
<property name="maxActive" value="${master.jdbc.pool.maxActive}" />
<property name="maxIdle" value="${master.jdbc.pool.maxIdle}" />
<property name="initialSize" value="${master.jdbc.pool.initialSize}" />
<property name="defaultAutoCommit" value="false" />
<!-- 连接Idle一个小时后超时 -->
<property name="timeBetweenEvictionRunsMillis" value="3600000" />
<property name="minEvictableIdleTimeMillis" value="3600000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<property name="validationQuery" value="SELECT 1" />
<property name="logAbandoned" value="false" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="60" />
</bean>
<bean id="slave" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${slave.jdbc.driver}" />
<property name="url" value="${slave.jdbc.url}" />
<property name="username" value="${slave.jdbc.username}" />
<property name="password" value="${slave.jdbc.password}" />
<!-- Connection Pooling Info -->
<property name="maxActive" value="${slave.jdbc.pool.maxActive}" />
<property name="maxIdle" value="${slave.jdbc.pool.maxIdle}" />
<property name="initialSize" value="${slave.jdbc.pool.initialSize}" />
<property name="defaultAutoCommit" value="false" />
<!-- 连接Idle一个小时后超时 -->
<property name="timeBetweenEvictionRunsMillis" value="3600000" />
<property name="minEvictableIdleTimeMillis" value="3600000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<property name="validationQuery" value="SELECT 1" />
<property name="logAbandoned" value="false" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="60" />
</bean>
</beans>
app.properties
master.jdbc.driver=com.mysql.jdbc.Driver
master.jdbc.url=jdbc:mysql://120.25.155.55:3306/test
master.jdbc.username=test
master.jdbc.password=!QAZxsw2
master.jdbc.pool.maxActive=60
master.jdbc.pool.maxIdle=20
master.jdbc.pool.initialSize=10
slave.jdbc.driver=com.mysql.jdbc.Driver
slave.jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true
slave.jdbc.username=root
slave.jdbc.password=
slave.jdbc.pool.maxActive=60
slave.jdbc.pool.maxIdle=20
slave.jdbc.pool.initialSize=10
DynamicDataSource.java
package com.test.holder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getDBType();
}
}
DBContextHolder.java
package com.test.holder;
public class DBContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDBType(String dbType) {
contextHolder.set(dbType);
}
public static String getDBType() {
return contextHolder.get();
}
public static void clearDBType() {
contextHolder.remove();
}
}
DataSource.java
package com.test.holder;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DataSource {
Source value() default Source.master;
}
Source.java
package com.test.holder;
public enum Source {
/* 主库 */master, /* 从库 */slave
}
UserMapper.java
package com.test.dao.mybatis;
import org.apache.ibatis.annotations.Param;
import com.test.model.UserModel;
public interface UserMapper {
UserModel findByUserId(@Param("userId")Long userId);
}
UserModel.java
package com.test.model;
public class UserModel {
private long id;
private String nickname;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.dao.mybatis.UserMapper">
<resultMap id="userModel" type="com.test.model.UserModel" >
<result property="id" column="id" />
<result property="nickname" column="nickname" />
</resultMap>
<select id="findByUserId" resultMap="userModel" >
select id , nickname from db_user where id=#{userId}
</select>
</mapper>
UserService.java
package com.test.service;
import com.test.model.UserModel;
public interface UserService {
UserModel findByMasterUserId(long userId);
UserModel findBySlaveUserId(long userId);
}
UserServiceImpl.java
package com.test.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.test.dao.mybatis.UserMapper;
import com.test.holder.DataSource;
import com.test.holder.Source;
import com.test.model.UserModel;
import com.test.service.UserService;
@Service("userServiceImpl")
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Transactional(rollbackFor={Exception.class})
@DataSource(value=Source.master)
public UserModel findByMasterUserId(long userId){
return this.userMapper.findByUserId(userId);
}
@Transactional(rollbackFor={Exception.class})
@DataSource(value=Source.slave)
public UserModel findBySlaveUserId(long userId){
return this.userMapper.findByUserId(userId);
}
}
aop拦截
DataSourceContextAop.java
package com.test.aop;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.test.holder.DBContextHolder;
import com.test.holder.DataSource;
@Aspect
@Order(value=1)
@Component
public class DataSourceContextAop {
@Around("execution(@com.test.holder.DataSource * com.test.service.impl.*.*(..))")
public Object setDynamicDataSource(ProceedingJoinPoint pjp) throws Throwable {
Method method = this.getMethod(pjp);
DataSource dataSource = method.getAnnotation(DataSource.class);
if (dataSource != null) {
DBContextHolder.setDBType(dataSource.value().name());
}
return pjp.proceed();
}
public Method getMethod(JoinPoint pjp) {
Method method = null;
MethodSignature signature = (MethodSignature) pjp.getSignature();
method = signature.getMethod();
return method;
}
}
最后测试
Test.java
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.test.service.UserService;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ac.getBean("userServiceImpl");
System.out.println(userService.findByMasterUserId(1000001).getNickname());
System.out.println(userService.findBySlaveUserId(1000001).getNickname());
}
}
谢谢
而外加个hibernate和mybatis混用的配置
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
">
<description>Spring公共配置 </description>
<!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
<context:component-scan base-package="com.test">
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:app.properties</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource" />
</bean>
<!-- Jpa Entity Manager 配置 -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dynamicDataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<property name="packagesToScan" value="com.test.entity" />
<property name="jpaProperties">
<props>
<!-- <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory
</prop>
<prop key="net.sf.ehcache.configurationResourceName">ehcache/ehcache-hibernate.xml</prop> -->
<!-- 命名规则 My_NAME->MyName -->
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
<bean id="hibernateJpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform">
<bean factory-method="getDialect"
class="org.springside.modules.persistence.Hibernates">
<constructor-arg ref="dynamicDataSource" />
</bean>
</property>
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<!-- MyBatis配置 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="typeAliasesPackage" value="com.test.model" />
<property name="mapperLocations" value="classpath*:/mybatis/*Mapper.xml" />
<property name="dataSource">
<ref bean="dynamicDataSource" />
</property>
</bean>
<!-- 扫描basePackage下所有以@MyBatisRepository标识的 接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.dao.mybatis" />
<!-- <property name="annotationClass" value="jarlun.framework.core.base.mybatis.MyBatisRepository"
/> -->
</bean>
<bean id="dynamicDataSource" class="com.test.holder.DynamicDataSource">
<!-- 通过key-value的形式来关联数据源 -->
<property name="targetDataSources">
<map key-type ="java.lang.String">
<entry value-ref="master" key="master"></entry>
<entry value-ref="slave" key="slave"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="master" />
</bean>
<!-- JSR303 Validator定义 -->
<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册 -->
<!-- 建立视图内拦截器来解决JPA中访问延迟加载属性时产生的无会话异常 LazyInitializationException: could
not initialize proxy no session -->
<!-- 此拦截器会注入到servlet配置中的DefaultAnnotationHandlerMapping中 -->
<bean id="master" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${master.jdbc.driver}" />
<property name="url" value="${master.jdbc.url}" />
<property name="username" value="${master.jdbc.username}" />
<property name="password" value="${master.jdbc.password}" />
<!-- Connection Pooling Info -->
<property name="maxActive" value="${master.jdbc.pool.maxActive}" />
<property name="maxIdle" value="${master.jdbc.pool.maxIdle}" />
<property name="initialSize" value="${master.jdbc.pool.initialSize}" />
<property name="defaultAutoCommit" value="false" />
<!-- 连接Idle一个小时后超时 -->
<property name="timeBetweenEvictionRunsMillis" value="3600000" />
<property name="minEvictableIdleTimeMillis" value="3600000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<property name="validationQuery" value="SELECT 1" />
<property name="logAbandoned" value="false" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="60" />
</bean>
<bean id="slave" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${slave.jdbc.driver}" />
<property name="url" value="${slave.jdbc.url}" />
<property name="username" value="${slave.jdbc.username}" />
<property name="password" value="${slave.jdbc.password}" />
<!-- Connection Pooling Info -->
<property name="maxActive" value="${slave.jdbc.pool.maxActive}" />
<property name="maxIdle" value="${slave.jdbc.pool.maxIdle}" />
<property name="initialSize" value="${slave.jdbc.pool.initialSize}" />
<property name="defaultAutoCommit" value="false" />
<!-- 连接Idle一个小时后超时 -->
<property name="timeBetweenEvictionRunsMillis" value="3600000" />
<property name="minEvictableIdleTimeMillis" value="3600000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<property name="validationQuery" value="SELECT 1" />
<property name="logAbandoned" value="false" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="60" />
</bean>
</beans>