- 浏览: 1566291 次
文章分类
- 全部博客 (557)
- Spring 3 系列 (26)
- Spring 3 (4)
- oracle (7)
- java (6)
- css3 (1)
- andorid (11)
- IE中页面不居中 (1)
- crm (1)
- ibatis (1)
- jdbc (1)
- javacore (1)
- IT 生活 (3)
- 创业的简单感受 (1)
- web前端 (1)
- Java静态代理 (1)
- pdf (6)
- 模拟 (1)
- 数论 (1)
- ACM_POJ (2)
- C/C++求职面试必备考点 (1)
- 学习Android遇到的错误 (1)
- 嵌入式学习 (1)
- magento付费模板! (1)
- PHP (1)
- Oracle 开发 (1)
- MSSQL (1)
- javascript (6)
- 随感随想 (1)
- RobotFramework (1)
- Ajax (2)
- 数据库复习 (1)
- Java Web (1)
- Way (1)
- eclipse (1)
- 分布式 (1)
- 【ASP.NET开发】 (1)
- 搜索 (1)
- UML建模 (1)
- ANDROID (2)
- 编程技巧 (1)
- 程序员 (2)
- C语言相关 (1)
- Struts2 (1)
- 精品下载资源推荐 (1)
- CUDA (1)
- MFC (1)
- 游戏编程 (1)
- oracle数据库 (1)
- 暴力求解--哈希表 (1)
- 个人文章 (1)
- 最小生成树 (1)
- linux 基础 (1)
- Flex (1)
- Linux (1)
- UML (1)
- 云计算 (1)
- android ListView (1)
- java数据库连接池 (1)
- cxf (1)
- javas (0)
- jquery (2)
最新评论
-
lj杰:
您好,最近项目涉及这这方面的技术,能分享下源码不,小弟非常感谢 ...
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能 -
成大大的:
Android自动化测试从入门到精通网盘地址:https:// ...
4种手机自动化测试框架介绍 -
u012944589:
[size=xx-large][size=xx-small][ ...
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能 -
stone520520:
同求源码,这几天正想研究一下视频的相关功能mail: 1862 ...
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能 -
zhen8023wan:
源代码可以发给我一份吗?谢谢!qq邮箱:1796482787@ ...
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能
今天碰见Spring + 多个数据源的问题,正好有这篇文章,给大家分享一下
在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在 spring 和 hibernate 框架中总是配置一个数据源,因而 sessionFactory 的 dataSource 属性总是指向这个数据源并且恒定不变,所有 DAO 在使用 sessionFactory 的时候都是通过这个数据源访问数据库。但是现在,由于项目的需要,我们的 DAO 在访问 sessionFactory 的时候都不得不在多个数据源中不断切换,问题就出现了:如何让 sessionFactory 在执行数据持久化的时候,根据客户的需求能够动态切换不同的数据源?我们能不能在 spring 的框架下通过少量修改得到解决?是否有什么设计模式可以利用呢?
问题的分析
我首先想到在 spring 的 applicationContext 中配置所有的 dataSource 。这些 dataSource 可能是各种不同类型的,比如不同的数据库: Oracle 、 SQL Server 、 MySQL 等,也可能是不同的数据源:比如 apache 提供的 org.apache.commons.dbcp.BasicDataSource 、 spring 提供的 org.springframework.jndi.JndiObjectFactoryBean 等。然后 sessionFactory 根据客户的每次请求,将 dataSource 属性设置成不同的数据源,以到达切换数据源的目的。
但是,我很快发现一个问题:当多用户同时并发访问数据库的时候会出现资源争用的问题。这都是“单例模式”惹的祸。众所周知,我们在使用 spring 框架的时候,在 beanFactory 中注册的 bean 基本上都是采用单例模式,即 spring 在启动的时候,这些 bean 就装载到内存中,并且每个 bean 在整个项目中只存在一个对象。正因为只存在一个对象,对象的所有属性,更准确说是实例变量,表现得就如同是个静态变量(实际上“静态”与“单例”往往是非常相似的两个东西,我们常常用“静态”来实现“单例”)。拿我们的问题来说, sessionFactory 在整个项目中只有一个对象,它的实例变量 dataSource 也就只有一个,就如同一个静态变量一般。如果不同的用户都不断地去修改 dataSource 的值,必然会出现多用户争用一个变量的问题,对系统产生隐患。
通过以上的分析,解决多数据源访问问题的关键,就集中在 sessionFactory 在执行数据持久化的时候,能够通过某段代码去根据客户的需要动态切换数据源,并解决资源争用的问题。
问题的解决
(一) 采用 Decorator 设计模式
要解决这个问题,我的思路锁定在了这个 dataSource 上了。如果 sessionFactory 指向的 dataSource 可以根据客户的需求去连接客户所需要的真正的数据源,即提供动态切换数据源的功能,那么问题就解决了。那么我们怎么做呢?去修改那些我们要使用的 dataSource 源码吗?这显然不是一个好的方案,我们希望我们的修改与原 dataSource 代码是分离的。根据以上的分析,使用 GoF 设计模式中的 Decorator 模式(装饰者模式)应当是我们可以选择的最佳方案。
什么是“ Decorator 模式”?简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个 Decorator 套在原有代码外面。当我们使用 Decorator 的时候与原类完全一样,当 Decorator 的某些功能却已经修改为了我们需要修改的功能。 Decorator 模式的结构如图。
我们本来需要修改图中所有具体的 Component 类的一些功能,但却并不是去直接修改它们的代码,而是在它们的外面增加一个 Decorator 。 Decorator 与具体的 Component 类都是继承的 AbstractComponent ,因此它长得和具体的 Component 类一样,也就是说我们在使用 Decorator 的时候就如同在使用 ConcreteComponentA 或者 ConcreteComponentB 一样,甚至那些使用 ConcreteComponentA 或者 ConcreteComponentB 的客户程序都不知道它们用的类已经改为了 Decorator ,但是 Decorator 已经对具体的 Component 类的部分方法进行了修改,执行这些方法的结果已经不同了。
(二) 设计 MultiDataSource 类
现在回到我们的问题,我们需要对 dataSource 的功能进行变更,但又不希望修改 dataSource 中的任何代码。我这里指的 dataSource 是所有实现 javax.sql.DataSource 接口的类,我们常用的包括 apache 提供的 org.apache.commons.dbcp.BasicDataSource 、 spring 提供的 org.springframework.jndi.JndiObjectFactoryBean 等,这些类我们不可能修改它们本身,更不可能对它们一个个地修改以实现动态分配数据源的功能,同时,我们又希望使用 dataSource 的 sessionFactory 根本就感觉不到这样的变化。 Decorator 模式就正是解决这个问题的设计模式。
首先写一个 Decorator 类,我取名叫 MultiDataSource,通过它来动态切换数据源 。同时在配置文件中将sessionFactory的dataSource属性由原来的某个具体的dataSource改为MultiDataSource。如图:
对比原Decorator 模式, AbstractComponent 是一个抽象类,但在这里我们可以将这个抽象类用接口来代替,即 DataSource 接口,而 ConcreteComponent 就是那些 DataSource 的实现类,如 BasicDataSource 、 JndiObjectFactoryBean 等。 MultiDataSource 封装了具体的dataSource,并实现了数据源动态切换:
- public class MultiDataSource implements DataSource {
- private DataSource dataSource = null ;
- public MultiDataSource(DataSource dataSource){
- this .dataSource = dataSource;
- }
- /* (non-Javadoc)
- * @see javax.sql.DataSource#getConnection()
- */
- public Connection getConnection() throws SQLException {
- return getDataSource().getConnection();
- }
- //其它DataSource接口应当实现的方法
- public DataSource getDataSource(){
- return this .dataSource;
- }
- }
- public void setDataSource(DataSource dataSource) {
- this .dataSource = dataSource;
- }
- }
客户在发出请求的时候,将dataSourceName放到request中,然后把request中的数据源名通过调用newMultiDataSource(dataSource) 时可以告诉 MultiDataSource 客户需要的数据源,就可以实现动态切换数据源了。但细心的朋友会发现这在单例的情况下就是问题的,因为 MultiDataSource 在系统中只有一个对象,它的实例变量 dataSource 也只有一个,就如同一个静态变量一般。正因为如此, 单例模式让许多设计模式都不得不需要更改,这将在我的《“单例”更改了我们的设计模式》中详细讨论。那么,我们在单例模式下如何设计呢?
(三) 单例模式下的 MultiDataSource
在单例模式下,由于我们在每次调用 MultiDataSource 的方法的时候, dataSource 都可能是不同的,所以我们不能将 dataSource 放在实例变量 dataSource 中,最简单的方式就是在方法 getDataSource() 中增加参数,告诉 MultiDataSource 我到底调用的是哪个 dataSource :
值得一提的是,我需要的数据源已经都在spring
的配置文件中注册,
dataSourceName
就是其对应的
id
。
为了得到spring
的
ApplicationContext
,
MultiDataSource
类必须实现接口
org.springframework.context.ApplicationContextAware
,并且实现方法:
如此这样,我就可以通过this
.
applicationContext
.getBean(dataSourceName)
得到
dataSource
了。
查看以上设计,
MultiDataSource
依然无法运行,因为用户在发出请求时,他需要连接什么数据库,其数据源名是放在
request
中的,要将
request
中的数据源名传给
MultiDataSource
,需要经过
BUS
和
DAO
,也就是说为了把数据源名传给
MultiDataSource
,
BUS
和
DAO
的所有方法都要增加
dataSourceName
的参数,这是我们不愿看到的。写一个类,通过线程的方式跳过
BUS
和
DAO
直接传递给
MultiDataSource
是一个不错的设计:
做一个filter
,每次客户发出请求的时候就调用
SpObserver.petSp
(
dataSourceName
)
,将
request
中的
dataSourceName
传递给
SpObserver
对象。
最后修改
MultiDataSource
的方法
getDataSource()
:
完整的MultiDataSource
代码在附件中。
通过以上方案,我们解决了动态分配数据源的问题,但你可能提出疑问:方案中的数据源都是配置在
spring
的
ApplicationContext
中,如果我在程序运行过程中动态添加数据源怎么办?这确实是一个问题,而且在我们的项目中也确实遇到。
spring
的
ApplicationContext
是在项目启动的时候加载的。加载以后,我们如何动态地加载新的
bean
到
ApplicationContext
中呢?我想到如果用
spring
自己的方法解决这个问题就好了。所幸的是,在查看
spring
的源代码后,我找到了这样的代码,编写了
DynamicLoadBean
类,只要
调用loadBean()
方法,就可以将某个或某几个配置文件中的
bean
加载到
ApplicationContext
中(见附件)。不通过配置文件直接加载对象,在
spring
的源码中也有,感兴趣的朋友可以自己研究。
在完成了所有这些设计以后,我最后再唠叨一句。我们应当在
spring
中做如下配置:
其中dataSource
属性实际上更准确地说应当是
defaultDataSource
,即
spring
启动时以及在客户没有指定数据源时应当指定的默认数据源。
以上方案与其它方案相比,它有哪些优势呢?
首先,这个方案完全是在
spring
的框架下解决的,数据源依然配置在
spring
的配置文件中,
sessionFactory
依然去配置它的
dataSource
属性,它甚至都不知道
dataSource
的改变。唯一不同的是在真正的
dataSource
与
sessionFactory
之间增加了一个
MultiDataSource
。
其次,实现简单,易于维护。这个方案虽然我说了这么多东西,其实都是分析,真正需要我们写的代码就只有
MultiDataSource
、
SpObserver
两个类。
MultiDataSource
类真正要写的只有
getDataSource()
和
getDataSource(sp)
两个方法,而
SpObserver
类更简单了。实现越简单,出错的可能就越小,维护性就越高。
最后,这个方案可以使单数据源与多数据源兼容。这个方案完全不影响
BUS
和
DAO
的编写。如果我们的项目在开始之初是单数据源的情况下开发,随着项目的进行,需要变更为多数据源,则只需要修改
spring
配置,并少量修改
MVC
层以便在请求中写入需要的数据源名,变更就完成了。如果我们的项目希望改回单数据源,则只需要简单修改配置文件。这样,为我们的项目将增加更多的弹性。
特别说明:实例中的DynamicLoadBean在web环境下运行会出错,需要将类中AbstractApplicationContext改为org.springframework.context.ConfigurableApplicationContext。
(四)
通过线程传递
dataSourceName
(五)
动态添加数据源
(六)
在
spring
中配置
该方案的优势
- example.rar (32.1 KB)
- 下载次数: 57
评论
已经上传
已经上传
发表评论
-
Spring Batch学习(一)介绍
2015-01-08 17:17 8450为什么我们需要批处理? 我们不会总是想要立即得到需要的信 ... -
spring包详解
2012-04-22 14:58 1721下载的spring包中文件及各种包众多,在项目中往往只有 ... -
我的spring学习笔记2-IoC(反向控制 依赖注入)
2012-04-10 07:50 2776IoC(反向控制 依赖注入)这是Spring提出来了,这也是S ... -
我的spring学习笔记1-spring 简介
2012-04-10 07:49 21831.1. 概览 ... -
我的spring学习笔记15-容器扩展点之PropertyOverrideConfigurer
2012-04-22 14:55 1896PropertyOverrideConfigurer类似于Pr ... -
我的spring学习笔记14-容器扩展点之PropertyPlaceholderConfigurer
2012-04-22 14:55 1870PropertyPlaceholderConfigurer是个 ... -
我的spring学习笔记10-轻量级_Spring框架
2012-04-14 21:59 1998一、问题提问: ... -
我的spring学习笔记9-Spring使用工厂方法实例化Bean的注意点
2012-04-14 21:59 1584方法一: <bean id="m ... -
我的spring学习笔记8-Spring中Bean的实例化
2012-04-14 21:59 1500在Spring中要实例化一个Bean有几种方法: 1、最常用 ... -
我的spring学习笔记7-Spring的Bean配置文件给Bean定义别名
2012-04-14 21:59 3040本文介绍如何给Spring的Bean配置文件的Bean定义别名 ... -
我的spring学习笔记6-ApplicationContext实例化的参数兼容思想
2012-04-14 21:59 1511ApplicationContext能读取多个Bean定义文件 ... -
我的spring学习笔记5-如何使用ApplicationContext替换BeanFactory
2012-04-12 22:03 1910如何使用ApplicationContext替换BeanFac ... -
我的spring学习笔记4-ApplicationContext详解
2012-04-12 22:03 4361ontext的核心作用是ApplicationConte ... -
我的spring学习笔记3-BeanFactory 详解
2012-04-12 22:03 19811、BeanFactory是 ... -
我的spring学习笔记2-IoC(反向控制 依赖注入)
2012-04-12 22:03 1233IoC(反向控制 依赖注入)这是Spring提出来了,这也是S ... -
我的spring学习笔记-spring 简介
2012-04-12 22:03 15951.1. 概览 ... -
Spring中事件处理de小技巧
2012-04-08 12:01 1618Spring 中提供一些Aware相关de接口,Be ... -
关于使用Spring导致c3p0数据库死锁问题
2012-04-08 11:59 6509这个问题我实在是为整个 springsource 的员工蒙羞 ... -
SPRING多数据源切换的问题和解决方法
2012-04-08 11:56 4520在应用中,需要热切换数据源。但发现如下问题: J ... -
再析在spring框架中解决多数据源的问题
2012-04-08 11:52 1757在前面我写了《如何在 spring 框架中解决 ...
相关推荐
在多数据源的配置中,需要有一种机制来实现数据源的动态切换。这通常涉及到根据业务逻辑条件选择不同的数据源来执行数据库操作。在应用程序运行过程中,可以根据需要动态地切换数据源,这可能涉及到会话工厂中数据库...
首先,这个方案完全是在spring的框架下解决的,数据源依然配置在spring的配置文件中,sessionFactory依然去配置它的dataSource属性,它甚至都不知道dataSource的改变。 其次,实现简单,易于维护。这个方案虽然我说...
在SSH框架中,多数据源配置可以通过使用Spring框架的数据源配置来实现。Spring框架提供了多种数据源配置方式,包括基于XML的配置和基于Annotation的配置。在这个例子中,我们使用基于XML的配置方式来实现多数据源...
2. **动态切换数据源**:在Spring框架中,我们可以利用AOP(面向切面编程)和ThreadLocal来实现数据源的动态切换。创建一个自定义的数据源切换注解,比如`@SwitchDataSource`,并在需要切换数据源的方法上使用。通过...
在多数据源配置中,Spring能够帮助管理不同的数据源,通过配置bean来切换和控制数据源的使用。 **SpringMVC** 是Spring框架的一部分,专为Web开发设计。它简化了模型-视图-控制器(Model-View-Controller,MVC)的...
在多数据源的场景下,Hibernate提供了灵活的数据源配置,可以在同一个应用中管理多个数据库连接。这通常通过定义不同的SessionFactory配置和DataSource实例来实现。 **MyBatis** 则是一个轻量级的ORM框架,它比...
5. **事务管理**:在多数据源环境下,事务管理也需要特别注意。Spring的PlatformTransactionManager应配置为DataSourceTransactionManager,并且需要确保它知道如何处理多个数据源。在事务开始时,事务管理器会根据...
在多数据源场景下,Hibernate可以配置为连接不同的数据库,使得应用可以根据业务需求灵活切换数据源。 **多数据源** 是指在一个应用中管理多个独立的数据库连接。在本项目中,数据源被配置为Hibernate和Datastore,...
在Java Spring框架中,多数据源的实现是一个重要的特性,特别是在大型企业级应用中,它允许应用程序连接到多个数据库,从而实现数据隔离、负载均衡或读写分离等高级功能。本教程将深入探讨如何在Spring中配置和管理...
Spring多数据源允许我们在一个应用中同时管理多个数据库连接,通过切换不同的数据源来满足不同业务的需求。实现这一功能的关键在于Spring的DataSourceTransactionManager和AbstractRoutingDataSource。 1. **...
在Spring框架中,多数据源的支持使得应用可以同时连接并操作多个不同的数据库,这在分布式系统、微服务架构或者需要处理多种数据类型的场景下非常有用。"Spring动态切换多数据源Demo"是一个示例项目,它展示了如何在...
在多数据源环境中,每个数据源需要一个单独的SessionFactory。我们可以为每个数据源创建一个SessionFactory配置,并指定相应的DataSource,实体扫描路径,以及其他的Hibernate配置参数。 在"压缩包子文件的文件名称...
本文将深入探讨如何在一个基于Spring框架的应用中实现多数据源的动态切换,以"基于SSI+Oracle架构的多数据源动态切换实例"为例进行详细讲解。 首先,我们需要理解什么是多数据源。多数据源是指在一个应用中同时连接...
标签中的"源码"可能指的是理解MyBatis和Spring框架内部如何处理多数据源的关键代码,这有助于我们更深入地定制和优化解决方案。"工具"可能是指像Druid、HikariCP这样的数据库连接池,它们在多数据源配置中起着至关...
在本项目中,我们将探讨如何利用MyBatis与Spring框架实现动态切换数据源的功能。首先,我们需要理解MyBatis和Spring的基本概念以及它们如何协同工作。 MyBatis是一个优秀的持久层框架,它简化了Java与数据库之间的...
在多数据源场景下,Mybatis可以通过SqlSessionFactoryBuilder创建多个SqlSessionFactory实例,每个实例对应一个数据源,从而实现数据源的隔离。 实现多数据源通常有以下步骤: 1. **配置数据源**:首先,你需要...
- 注意事务管理的配置,确保在多数据源环境下事务的一致性。 8. **应用场景**: - 分布式系统中,不同的服务可能需要连接不同的数据库。 - 高并发场景下,可以通过数据源分片来分散压力。 - 读写分离,主库负责...
- 在多数据源和AOP的测试中,我们需要模拟不同的数据源环境,确保在各种情况下,代码都能正确地选择并使用正确的数据源。 - 可以使用Spring的@Test注解和@MockBean来创建测试环境,模拟数据源切换,并验证AOP是否...