`
zhao103804
  • 浏览: 121475 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

spring 配置多数据源过程

 
阅读更多

这里使用AOP拦截注解来切换数据源。
1.    在数据源配置文件context.xml中增加新的数据源信息,使存在多个数据库服务可以访问。注意区别开jndi名称。
2.    在spring配置文件(一般是spring.xml)中增加新数据源的连接配置。
3.    新建多数据源类(比如MultipleDataSource.java),需要继承自org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
a)    增加静态属性用来保存数据源信息。因为线程间不需要访问对方的数据源,这里使用ThreadLocal保存各线程的数据源信息

public class DataSourceContextLocal
{
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

    public static void setDataSourceId(String dataSourceId)
    {
          //增加静态设置方法,用于给当前线程设置数据源
        contextHolder.set(dataSourceId);
    }

    public static String getDataSourceId()
    {
        return contextHolder.get();
    }

    public static void clearDataSourceId()
    {
        //增加静态清除方法,用于给无注解方法使用默认数据源
        contextHolder.remove();
    }
}

 

 

 

 b)    重写determineCurrentLookupKey()方法。该方法是spring jdbc用来从targetDataSources中查找数据源的,如果返回为null, 则使用defaultTargetDataSource指定的默认数据源(这些属性在第4步配置)

public class DynamicDataSource extends AbstractRoutingDataSource
{

    @Override
    protected Object determineCurrentLookupKey()
    {
        return DataSourceContextLocal.getDataSourceId();
    }

}

 4.    在spring.xml增加多数据源类的bean

<!-- 多数据源 -->
	<bean id="dynamicDataSource" class="com.iflytek.wh.base.dao.common.DynamicDataSource">
		<property name="targetDataSources">
			<map key-type="java.lang.String">
				<entry key="defaultDs" value-ref="defaultDs" />
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="defaultDs" />
	</bean>

 a)    配置属性defaultTargetDataSource,ref值为几个数据库连接中的某一个。当没有指定数据源时,默认使用该连接。
b)    配置属性targetDataSources,map的条目key自由定义,用来识别不同的数据源,value-ref指向对应的数据库连接。
6.    新增注解类,需要包含一个字符串属性,由于结合AOP所以要指定反射期可用,同时该注解作用于方法上:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 用于在dao层切换数据源
 * 
 * @author elsu@iflytek.com
 * @date 2016年3月29日 下午1:04:58
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSource
{
    String name() default DataSource.defaultDs;

    public static String defaultDs = "defaultDs";

    public static String otherDs = "otherDs";

    public static String usercenterDs = "usercenterDs";

}

 

 7.    新建一个AOP通知类,我们要在方法执行以前先切换数据源,所以要实现org.springframework.aop.MethodBeforeAdvice接口,重写before(Method method, Object[] args, Object target)方法:

 

import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

import com.iflytek.wh.base.support.annotation.DataSource;

public class DataSourceSwitching implements MethodBeforeAdvice, AfterReturningAdvice {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        String fullMethodName = target.getClass().getSimpleName() + "." + method.getName();
        DataSource dataSource = method.getAnnotation(DataSource.class);
        if (dataSource != null) {
            String dataSourceName = dataSource.name();
            logger.debug(fullMethodName + ":切换到数据源" + dataSourceName);
            DataSourceContextLocal.setDataSourceId(dataSourceName);
        } else {
            logger.debug(fullMethodName + ":使用默认数据源");
            DataSourceContextLocal.clearDataSourceId();
        }
    }

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
            throws Throwable {
        // DataSourceContextLocal.clearDataSourceId();
    }
}

 

 8.    由于接口实现配置了事务管理,事务的优先级会高于数据源切换。一旦事务开启,再切换数据源是无效的,所以这里需要修改它们的次序
a)    通知类要实现org.springframework.core.Ordered接口,并重写getOrder()方法,令其返回1;

<!-- 事务 -->
	<bean id="txManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
		p:dataSource-ref="dynamicDataSource" />
	<tx:annotation-driven transaction-manager="txManager"
		order="1" />

 样,Spring会优先执行通知类方法,之后再开启事务。
9.    在需要切换数据源的接口方法上(必须是接口里的方法,在实现方法上无效)增加注解@BiDSChoicer(dsName="dsname"),属性值必须是配置的targetDataSources属性的条目key。
10.    在spring.xml里面新建通知类的bean,假设id是advice
11.    定义切入点,expression属性要根据情况具体修改,指向实现类

 

<!-- 注解切换数据源 -->
	<aop:config>
		<aop:pointcut id="daoMapping"
			expression="execution(* com.iflytek..service.*.*(..))" />
		<!-- 关键配置,切换数据源一定要比持久层代码更先执行(事务也算持久层代码) -->
		<aop:advisor advice-ref="dataSourceSwitching"
			pointcut-ref="daoMapping" order="0" />
	</aop:config>
	<bean id="dataSourceSwitching" class="com.iflytek.wh.base.dao.common.DataSourceSwitching" />

 这样配置以后,需要修改数据源的接口方法只要在其上增加注解即可。AOP拦截方法后会先对数据源进行设置,有注解的根据注解属性设置,没有注解的设置为使用默认数据源。对于AOP不拦截的则使用默认数据源。

 

 

参考地址:

http://www.cnblogs.com/davidwang456/p/4318303.html

http://somefuture.iteye.com/blog/2306320

分享到:
评论

相关推荐

    spring 整合 mybatis 中数据源的几种配置方式(总结篇)

    因为spring 整合mybatis的过程中, 有好几种整合方式,尤其是数据源那块,经常看到不一样的配置方式,总感觉有点乱,所以今天有空总结下,感兴趣的朋友跟随脚本之家小编一起学习吧

    Spring Jpa多数据源工程配置过程解析

    主要介绍了Spring Jpa多数据源工程配置过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    Spring数据源及配置文件数据加密实现过程详解

    主要介绍了Spring数据源及配置文件数据加密实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    spring-boot-mybatis-multidatasource多数据源配置(oracle)

    3, application.yml中配置了双数据源,根据需要可以加多个数据源,同时要在datasource包中新建数据源配置,参考那两个配置。 4, 启动项目,测试接口在DataSourceController中,只用注入相关的bean就能使用。 5, 使用...

    Spring数据库多数据源路由配置过程图解

    主要介绍了Spring数据库多数据源路由配置过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    SpringBoot整合Oracle数据库使用双数据源

    本资源使用SpringBoot整合Oracle数据库连接双数据源,源码已进行测试真是有效,使用时更改bootstrap.yml数据库配置即可

    birt百灵报表数据源配置全集

    包含eclipse百灵报表项目的所有数据源的配置及创建例子,苦心收集整理,...包括动态数据源、外部数据源、jdbc数据源、spring数据源、hibernate数据源、web Service数据源、javascript数据源、存储过程数据源等。

    基于Spring Boot的数据质量管理平台设计源码

    该平台是一个支持多种异构数据源的数据质量管理平台,用于解决业务系统运行、数据中心建设及数据治理过程中的各种数据质量问题。它基于Spring Boot,依赖于Linkis进行数据计算,提供数据质量模型构建和数据质量模型...

    Hibernate Spring MySQL项目配置图解

    这是本人上课过程中为学生讲解hibernate、spring和mysql开发简单项目的截图汇集,大家需要先自己完成数据库以及JDBC数据源的配置,之后按照该截图的顺序就能完成一个最简单的支持数据库事务处理的SH系统,(如果使用...

    spring搭建分布式事务所需嘉宝atomikos加druid配置分布式事务

    spring+druid+atomikos分布式事务,多数据源切换!其中包括配置文件

    spring源代码解析

    从加载过程我们可以看到,首先从Servlet事件中得到ServletContext,然后可以读到配置好的在web.xml的中的各个属性值,然后ContextLoder实例化WebApplicationContext并完成其载入和初始化作为根上下文。当这个根上...

    Kotlin版本微服务框架参考(亲手搭建 修改Redis及数据库配置可启动)

    ps:此处意味着理论上可以添加无限多个数据源,适合一服务多数据库且需要运行过程动态切换数据源的情况 @TargetDataSource:数据源切换注解,参数未数据源名称,如master/slave/slave2 DataSourceRouting:动态数据...

    spring mybatis多数据源实例详解

    本文主要介绍sping mybatis多数据源处理,在开发过程中经常会遇到多个数据库,这里给大家举例说明如何处理,希望能帮助有需要的小伙伴

    高级开发spring面试题和答案.pdf

    @transaction多个数据源事务怎么指定数据源 传播特性有几种?7种; 某一个事务嵌套另一个事务的时候怎么办? REQUIRED_NEW和REQUIRED区别 Spring的事务是如何回滚的,实现原理; 抽象类和接口的区别,什么时候用...

    详细介绍Spring和SpringBoot的区别

    - **Spring**:配置较为繁琐,需要使用XML文件或Java类进行显式配置,包括定义Bean、配置数据源、事务管理等。 - **Spring Boot**:简化了配置过程,通过`application.properties`或`application.yml`文件进行配置...

    Spring.3.x企业应用开发实战(完整版).part2

    2.2.3 类包及Spring配置文件规划 2.3 持久层 2.3.1 建立领域对象 2.3.2 UserDao 2.3.3 LoginLogDao 2.3.4 在Spring中装配DAO 2.4 业务层 2.4.1 UserService 2.4.2 在Spring中装配Service 2.4.3 单元测试 2.5 展现层 ...

    springEmbeddedTomcatJNDI:Spring Boot 2.x嵌入式tomcat JNDI数据源(开发配置文件)+ WAR

    Spring Boot 2.x嵌入式tomcat JNDI数据源(开发配置文件)+ WAR 该代码旨在通过JNDI数据源查找保持数据库访问。 在开发中,使用配置了JNDI数据源的嵌入式tomcat运行在部署为WAR时,它将在服务器上查找真实的JDNI...

    Spring Data JPA 原理与实战2021年

    │ 18 生产环境多数据源的处理方法有哪些?.mp4 │ 19 如何搞清楚事务、连接池的关系?正确配置是怎样的?.mp4 │ 20 Spring JPA 中的 Hibernate 加载过程与配置项是怎么回事?.mp4 │ 21 Peritence Context 所...

    Spring中文帮助文档

    3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ApplicationContext? 3.8.2. 利用MessageSource实现国际化 ...

    Spring API

    3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ApplicationContext? 3.8.2. 利用MessageSource实现国际化 ...

Global site tag (gtag.js) - Google Analytics