ssm 多数据源 注解版本

application.xml 配置如下

XML 复制代码
<!-- 使用 DruidDataSource 数据源 -->
 <bean id="primaryDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
 </bean>
<!-- 使用 数据源 1-->
 <bean id="logDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
 </bean>

 <!-- 配置动态加载数据源 -->
    <bean id="druidDynamicDataSource" class="com.iss.sso.utils.DynamicDataSource">
        <property name="defaultTargetDataSource" ref="primaryDataSource" />
        <property name="targetDataSources">
            <map>
                <entry key="primaryDataSource" value-ref="primaryDataSource"/>
                <entry key="scheduleDataSource" value-ref="logDataSource"/>
                
            </map>
        </property>
    </bean>
<!--3.配置SqlSessionFactory对象-->
 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        <!--往下才是mybatis和spring真正整合的配置-->
        <!--注入数据库连接池-->
            <property name="dataSource" ref="druidDynamicDataSource"/>
        <!--
            配置mybatis全局配置文件:mybatis-config.xml
            指定Mybatis的配置文件位置。如果指定了该属性,
            那么会以该配置文件的内容作为配置信息构建对应的SqlSessionFactoryBuilder,
            但是后续属性指定的内容会覆盖该配置文件里面指定的对应内容
        -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--
            扫描entity包,使用别名,多个用;隔开
            一般对应实体类所在的包,这个时候会自动取对应包中不包括包名的简单类名作为包括包名的别名。
            多个package之间可以用逗号或者分号等来进行分隔。(value的值一定要是包的全名)
        -->
        <property name="typeAliasesPackage" value="com.sso.**.domain"/>
        <!--
            扫描sql配置文件:mapper需要的xml文件
            Mapper文件存放的位置,当Mapper文件跟对应的Mapper接口处于同一位置的时候可以不用指定该属性的值
        -->
        <property name="mapperLocations" value="classpath:/mapper/*.xml"/>
     
    </bean>
-----     动态数据源
<bean id="dynamicDataSourceAspect" class="com.sso.utils.DynamicDataSourceAspect">
    </bean>
 <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--引入数据源-->
        <property name="dataSource" ref="druidDynamicDataSource"/>
    </bean>

    <!-- 开启事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

 <!--定义事务增强,并制定事务管理器  -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--设置传播行为-->
            <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"/>
            <tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT"/>
            <tx:method name="del*" propagation="REQUIRED" isolation="DEFAULT"/>
            <tx:method name="select*" propagation="SUPPORTS" isolation="DEFAULT" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT"/>
        </tx:attributes>
    </tx:advice>
 <aop:config proxy-target-class="true">
        <aop:pointcut id="myPointcut" expression="execution(* com.sso.*.dao.*.*(..))"/>
        <aop:advisor advice-ref="dynamicDataSourceAspect" pointcut-ref="myPointcut" order="1"/>
        <!--把事务控制在Service层-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" order="2"/>
    </aop:config>

动态数据源 核心类

java 复制代码
/**
 * 动态数据源加载
 *
 * @author
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);

    /**
     * 数据源标识,保存在线程变量中,避免多线程操作数据源时互相干扰
     */
    private static final ThreadLocal<String> key = new ThreadLocal<String>();

    @Override
    protected Object determineCurrentLookupKey() {
        logger.debug("===当前数据源: {}===", key.get());
        return key.get();
    }

    /**
     * 设置数据源
     *
     * @param dataSource 数据源名称
     */
    public static void setDataSource(String dataSource) {
        key.set(dataSource);
    }

    /**
     * 获取数据源
     *
     * @return
     */
    public static String getDatasource() {
        return key.get();
    }

    /**
     * 清除数据源
     */
    public static void clearDataSource() {
        key.remove();
    }

}

spring aop 植入

java 复制代码
@Aspect
@Order(-10)
@Component
public class DynamicDataSourceAspect implements MethodBeforeAdvice, AfterReturningAdvice {

    Logger log = LoggerFactory.getLogger("切换数据源");

    /**
     * 目标方法正常完成后被织入,关闭数据源
     *
     * @param o
     * @param method
     * @param objects
     * @param o1
     * @throws Throwable
     */
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) {
        //这里做一个判断,有使用DataSourceAnnotation注解时才关闭数据源,有一个主要的数据源,就没有必要每次都去关闭
        if (method.isAnnotationPresent(DataSourceAnnotation.class)) {
            DynamicDataSource.clearDataSource();
            log.debug("数据源已关闭");
        }
    }

    /**
     * 拦截目标方法,获取由@DataSourceAnnotation指定的数据源标识,设置到线程存储中以便切换数据源
     */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        if (method.isAnnotationPresent(DataSourceAnnotation.class)) {
        String clazzName = method.getDeclaringClass().getName();
        String methodName = method.getName();
            log.info("{}.{} 准备切换数据源", clazzName, methodName, DynamicDataSource.getDatasource());
            DataSourceAnnotation dataSourceAnnotation = method.getAnnotation(DataSourceAnnotation.class);
            DynamicDataSource.setDataSource(dataSourceAnnotation.value());
            log.info("{}.{} 数据源切换为:{}", clazzName, methodName, DynamicDataSource.getDatasource());
        } else {
            DynamicDataSource.setDataSource(DataSourceAnnotation.PRIMARY);
        }
    }
}
相关推荐
ademen1 分钟前
关于 IntelliJ IDEA 中频繁出现的 Kotlin 及其核心作用
java·开发语言·kotlin
薯条不要番茄酱7 分钟前
【JavaEE初阶】多线程重点知识以及常考的面试题-多线程进阶(一)
java·前端·java-ee
大苏打seven9 分钟前
Java学习笔记(多线程):ConditionObject 源码分析
java·笔记·学习
苹果酱056717 分钟前
redis系列--1.redis是什么
java·vue.js·spring boot·mysql·课程设计
卷不动的打工仔21 分钟前
Ubuntu利用docker搭建Java相关环境问题记录
java·ubuntu·docker
百锦再36 分钟前
Android Studio 中文字大小的单位详解
android·xml·java·ide·app·android studio
一只叫煤球的猫1 小时前
分布式-跨服务事务一致性的常见解决方案
java·分布式·后端
赤橙红的黄1 小时前
Spring编程式事务(本地事务)
java·数据库·spring
PHASELESS4111 小时前
Java排序算法百科全书:原理、实现与实战指南
java·数据结构·算法·排序算法
大胆刁民1 小时前
java 代理
java·后端