*SSM AOP简单配置动态数据库*
第一步,db.properties,配置数据源信息
#图个方便,均采用sqlserver
db1.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
db1.url=jdbc:sqlserver://localhost:1433;DatabaseName=db1
db1.username=sa
db1.password=sa
db2.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
db2.url=jdbc:sqlserver://localhost:1433;DatabaseName=db2
db2.username=sa
db2.password=sa
第二步,applicationContext.xml,配置数据源
<!-- 引入数据库配置文件,位置要正确 -->
<context:property-placeholder location="classpath:configs/db.properties"/>
<!--配置db1数据库-->
<bean id="db1DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass"><value>${db1.driver}</value></property>
<property name="jdbcUrl"><value>${db1.url}</value></property>
<property name="user"><value>${db1.username}</value></property>
<property name="password"><value>${db1.password}</value></property>
</bean>
<!--配置db2数据库-->
<bean id="db2DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass"><value>${db2.driver}</value></property>
<property name="jdbcUrl"><value>${db2.url}</value></property>
<property name="user"><value>${db2.username}</value></property>
<property name="password"><value>${db2.password}</value></property>
</bean>
第三步,DynamicDataSource.java,动态切换数据源类
package com.common.aop.dataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import com.common.aop.dataSource.DynamicDataSourceHolder;
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
//获取当前使用的数据源
return DynamicDataSourceHolder.getDataSource();
}
}
第四步,DynamicDataSourceHolder.java,动态切换数据源支持类
package com.common.aop.dataSource;
public class DynamicDataSourceHolder {
//数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();
public static final String DATA_SOURCE_DB1 = "db1DataSource";//对应动态数据源配置中的key
public static final String DATA_SOURCE_DB2 = "db2DataSource";
public static String getDataSource() {
return THREAD_DATA_SOURCE.get();
}
public static void setDataSource(String dataSource) {
THREAD_DATA_SOURCE.set(dataSource);
}
public static void clearDataSource() {
THREAD_DATA_SOURCE.remove();
}
}
第五步,applicationContext.xml,配置动态数据源
<!-- 动态DataSource配置,对应DynamicDataSource类 -->
<bean id="dynamicDataSource" class="com.common.aop.dataSource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<!-- 对应DynamicDataSourceHolder类 -->
<entry key="db1DataSource" value-ref="db1DataSource"/>
<entry key="db2DataSource" value-ref="db2DataSource"/>
</map>
</property>
<!-- 配置默认数据源 -->
<property name="defaultTargetDataSource" ref="db1DataSource"/>
</bean>
<!--整合mybatis-->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置MyBatis全局配置文件的位置 -->
<property name="configLocation" value="classpath:configs/mybatis-config.xml"></property>
<!-- 对应动态数据源配置 -->
<property name="dataSource" ref="dynamicDataSource"></property>
<!-- 指定mybatis,mapper文件的位置 -->
<property name="mapperLocations" value="classpath:com/*/*/dao/*.xml"></property>
</bean>
<!-- 配置扫描器,将mybatis接口的实现加入到ioc容器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描所有dao接口的实现,加入到ioc容器中 -->
<property name="basePackage" value="com.*.*.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sessionFactory"></property>
</bean>
第六步,MultipleDataSourceAspect.java,aop切换数据源
package com.common.aop.dataSource;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Order(-100) //这是为了保证aop在事务注解之前生效,值越小,优先级越高
public class MultipleDataSourceAspect {
/**
* 向db1下的所有实现切入数据源(默认数据源)
* 根据service层接口实现类区分数据库
*/
@Pointcut("execution( * com.db1.*.service.*Impl.*(..))")
public void cutIntoDb1() {}
@Before(value = "cutIntoDb1()")
public void beforeCutIntoDb1(JoinPoint joinPoint) {
System.out.println("切入db1数据库");
DynamicDataSourceHolder.setDataSource(DynamicDataSourceHolder.DATA_SOURCE_DB1);
}
/**
* 向db2下的所有实现切入数据源
*/
@Pointcut("execution( * com.db2.*.service.*Impl.*(..))")
public void cutIntoDb2() {}
@Before(value = "cutIntoDb1()")
public void beforeCutIntoDb1(JoinPoint joinPoint) {
System.out.println("切入db2数据库");
DynamicDataSourceHolder.setDataSource(DynamicDataSourceHolder.DATA_SOURCE_DB2);
}
@After(value = "cutIntoDb2()")
public void afterCutIntoDb2(JoinPoint point) {
//清理掉当前设置的数据源,让默认的数据源不受影响
System.out.println("清除db2数据库");
DynamicDataSourceHolder.clearDataSource();
}
}
第七步,applicationContext.xml,配置aop并扫描
<!-- 扫描aop,自动加载MultipleDataSourceAspect类 -->
<context:component-scan base-package="com.common.aop" />
<!-- 开启aop,简化写法,与下面的意思相同 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- 启动AOP AspectJ注解自动代理 -->
<!-- <aop:aspectj-autoproxy /> -->
<!-- 通知spring使用cglib而不是jdk的来生成代理方法 AOP可以拦截到Controller -->
<!-- <aop:config proxy-target-class="true"></aop:config> -->
到此,简单配置完成。
目录结构
参考:https://blog.csdn.net/yybk426/article/details/115123694
版权声明:本文为hsy1079120641原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。