在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户根据需要会去访问不同的数据库,而我们使用的spring和hibernate框架在使用的时候往往总是配置一个数据源,hibernate的sessionFactory在执行数据持久化的时候总是去访问这个数据源来连接数据库。这样,一个多数据源的问题出现了:如何让sessionFactory在执行数据持久化的时候,根据客户的需求访问不同的数据源?我们能不能在spring的框架下通过少量修改得到解决?是否有什么设计模式可以利用?
问题的分析
在现在的模式下,sessionFactory在执行数据持久化的时候为什么不能根据需要访问数据源呢?这都是“单例模式”惹的祸。众所周知,我们在使用spring框架的时候,在beanFactory中注册的bean基本上都是采用单例模式,即spring在启动的时候,这些bean就装载到内存中,并且每个bean在整个项目中只存在一个对象。正因为只存在一个对象,对象的所有属性,更准确说是实例变量,表现得就如同是个静态变量(实际上“静态”与“单例”往往是非常相似的两个东西,我们常常用“静态”来实现“单例”)。拿我们的问题来说,sessionFactory在整个项目中只有一个对象,它的实例变量dataSource也就只有一个,就如同一个静态变量一般。如果不同的用户都不断地去修改dataSource的值,必然会出现多用户争用一个变量的问题,对系统产生隐患。
- public class LocalSessionFactoryBean implements FactoryBean, InitializingBean, DisposableBean {
- ......
- private DataSource dataSource;
- ......
- public void setDataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- }
- ......
- }
问题的解决
(一)采用Decorator设计模式
要解决这个问题,我的思路锁定在了这个dataSource上了。如果我能将sessionFactory指定一个特殊的dataSource,这个dataSource它首先是一个dataSource,即实现了javax.sql.DataSource接口,同时,它又可以根据客户的需求去连接客户所需要的真正的dataSource,即提供动态分配数据源的功能,那么问题就解决了。根据以上的分析,使用设计模式中的Decorator模式(装饰者模式)应当是我们可以选择的最佳方案。
什么是“Decorator模式”?我们看看它的定义。Decorator模式是用于动态地为对象赋予另外的职责。如果一个父类的所有子类需要扩展(变更)某些功能,它为这些子类提供了一个灵活多变的替代类,这个类就叫Decorator。Decorator模式的结构如图。
举一个简单例子来说明:
我们定义了一个父类和它的子类:
- public abstract class AbstractComponent {
- public abstract Long methodA();
- public abstract String methodB();
- }
- public class ConcreteComponentA extends AbstractComponent{
- public long methodA() {
- return 10;
- }
- public String methodB() {
- return "Hellow world!";
- }
- }
- public class ConcreteComponentB extends AbstractComponent{
- public long methodA() {
- return 20;
- }
- public String methodB() {
- return "This is an example!";
- }
- }
现在我希望更改所有子类的方法methodA()和methodB()的功能,methodA()在原值的基础上加5,methodB()在原字符串前增加"Good morning! "。为了不修改原代码,我为它们增加一个Decorator类:
- public class Decorator extends AbstractComponent{
- private AbstractComponent component;
- public Decorator(AbstractComponent component){
- this.component = component;
- }
- public long methodA() {
- return component.methodA() + 5;
- }
- public String methodB() {
- return "Good morning! "+component.methodB();
- }
- }
再写一段代码来调用它们:
- public static void main(String[] args){
- AbstractComponent componentA = new ConcreteComponentA();
- AbstractComponent componentB = new ConcreteComponentB();
- System.out.println(componentA.methodA());
- System.out.println(componentA.methodB());
- System.out.println(componentB.methodA());
- System.out.println(componentB.methodB());
- componentA = new Decorator(componentA);
- componentB = new Decorator(componentB);
- System.out.println(componentA.methodA());
- System.out.println(componentA.methodB());
- System.out.println(componentB.methodA());
- System.out.println(componentB.methodB());
- }
从以上例子可以看出,我们本来需要修改所有具体的Component类的一些功能,但却并不是去直接修改它们的代码,而是在它们的外面增加一个Decorator。Decorator与具体的Component类都是继承的AbstractComponent,因此它长得和具体的Component类一样,也就是说我们在使用Decorator的时候就如同在使用ConcreteComponentA或者ConcreteComponentB一样,甚至那些使用ConcreteComponentA或者ConcreteComponentB的客户程序都不知道它们用的类已经改为了Decorator,但是Decorator已经对具体的Component类的部分方法进行了修改,执行这些方法的结果已经不同了。
| |
| |
|
|