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);
        }
    }
}
相关推荐
向宇it5 分钟前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
小蜗牛慢慢爬行7 分钟前
Hibernate、JPA、Spring DATA JPA、Hibernate 代理和架构
java·架构·hibernate
星河梦瑾1 小时前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富1 小时前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想1 小时前
JMeter 使用详解
java·jmeter
言、雲1 小时前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
TT哇1 小时前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
Yvemil72 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。2 小时前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
.生产的驴2 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven