论坛首页 Java版 Spring

如何在spring框架中解决多数据源的问题(下)

浏览 1373 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
时间:2007-04-19

上接《如何在spring框架中解决多数据源的问题(上)

(四)            通过线程传递dataSourceName

查看以上设计,MultiDataSource依然无法运行,因为用户在发出请求时,他需要连接什么数据库,其数据源名是放在request中的,要将request中的数据源名传给MultiDataSource,需要经过BUSDAO,也就是说为了把数据源名传给MultiDataSourceBUSDAO的所有方法都要增加dataSourceName的参数,这是我们不愿看到的。写一个类,通过线程的方式跳过BUSDAO直接传递给MultiDataSource是一个不错的设计:

java 代码
  1. public class SpObserver {   
  2.     private static ThreadLocal local = new ThreadLocal();   
  3.     public static void putSp(String sp) {   
  4.         local.set(sp);   
  5.     }   
  6.     public static String getSp() {   
  7.         return (String)local.get();   
  8.     }   
  9. }   

做一个filter,每次客户发出请求的时候就调用SpObserver.petSp(dataSourceName),将request中的dataSourceName传递给SpObserver对象。

最后修改MultiDataSource的方法getDataSource()

java 代码
  1. public DataSource getDataSource(){   
  2.         String sp = SpObserver.getSp();   
  3.         return getDataSource(sp);   
  4.     }   

完整的MultiDataSource代码在附件中。

(五)            动态添加数据源

通过以上方案,我们解决了动态分配数据源的问题,但你可能提出疑问:方案中的数据源都是配置在springApplicationContext中,如果我在程序运行过程中动态添加数据源怎么办?这确实是一个问题,而且在我们的项目中也确实遇到。springApplicationContext是在项目启动的时候加载的。加载以后,我们如何动态地加载新的beanApplicationContext中呢?我想到如果用spring自己的方法解决这个问题就好了。所幸的是,在查看spring的源代码后,我找到了这样的代码,编写了DynamicLoadBean类:

java 代码
  1. public class DynamicLoadBean implements ApplicationContextAware{   
  2.     private AbstractXmlApplicationContext applicationContext = null;   
  3.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {   
  4.         this.applicationContext = (AbstractXmlApplicationContext)applicationContext;   
  5.     }   
  6.     public AbstractXmlApplicationContext getApplicationContext() {   
  7.         return applicationContext;   
  8.     }   
  9.        
  10.     /**  
  11.      * 向spring的beanFactory动态地装载bean  
  12.      * @param configLocationString 要装载的bean所在的xml配置文件位置。  
  13.      */  
  14.     public void loadBean(String configLocationString){   
  15.         XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry)getApplicationContext().getBeanFactory());   
  16.         beanDefinitionReader.setResourceLoader(getApplicationContext());   
  17.         beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(getApplicationContext()));   
  18.         try {   
  19.             String[] configLocations = new String[]{configLocationString};   
  20.             for(int i=0;i
  21.                 beanDefinitionReader.loadBeanDefinitions(getApplicationContext().getResources(configLocations[i]));   
  22.         } catch (BeansException e) {   
  23.             e.printStackTrace();   
  24.         } catch (IOException e) {   
  25.             e.printStackTrace();   
  26.         }   
  27.     }   
  28. }   

调用loadBean()方法,就可以将某个或某几个配置文件中的bean加载到ApplicationContext中。不通过配置文件直接加载对象,在spring的源码中也有,感兴趣的朋友可以自己研究。

(六)            spring中配置

在完成了所有这些设计以后,我最后再唠叨一句。我们应当在spring中做如下配置:

xml 代码
  1. <bean id="dynamicLoadBean" class="com.htxx.service.dao.DynamicLoadBean">bean>  
  2. <bean id="dataSource" class="com.htxx.service.dao.MultiDataSource">  
  3.         <property name="dataSource">  
  4.             <ref bean="dataSource1" />  
  5.         property>  
  6.     bean>  
  7.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  8.         <property name="dataSource">  
  9.             <ref bean="dataSource" />  
  10.         property>  
  11.         ......   
  12.     bean>  

其中dataSource属性实际上更准确地说应当是defaultDataSource,即spring启动时以及在客户没有指定数据源时应当指定的默认数据源。

该方案的优势

以上方案与其它方案相比,它有哪些优势呢?

首先,这个方案完全是在spring的框架下解决的,数据源依然配置在spring的配置文件中,sessionFactory依然去配置它的dataSource属性,它甚至都不知道dataSource的改变。唯一不同的是在真正的dataSourcesessionFactory之间增加了一个MultiDataSource

其次,实现简单,易于维护。这个方案虽然我说了这么多东西,其实都是分析,真正需要我们写的代码就只有MultiDataSourceSpObserver两个类。MultiDataSource类真正要写的只有getDataSource()getDataSource(sp)两个方法,而SpObserver类更简单了。实现越简单,出错的可能就越小,维护性就越高。

最后,这个方案可以使单数据源与多数据源兼容。这个方案完全不影响BUSDAO的编写。如果我们的项目在开始之初是单数据源的情况下开发,随着项目的进行,需要变更为多数据源,则只需要修改spring配置,并少量修改MVC层以便在请求中写入需要的数据源名,变更就完成了。如果我们的项目希望改回单数据源,则只需要简单修改配置文件。这样,为我们的项目将增加更多的弹性。

   
论坛首页 Java版 Spring

跳转论坛:
JavaEye推荐