当前位置:编程学习 > JAVA >>

Spring动态注册bean实现动态多数据源

项目原来已经实现了多数据源配置,实现方式为在beans.xml文件中直接配置多个数据源bean,然后在使用数据源时通过HotSwappableTargetSource动态切换数据源(详细内容请Google)。可领导不满意,要求只在属性文件中配置相应的连接信息,并要求动态数据源除配置的属性外,其他属性都继承系统默认数据源(DataSource)的属性。然后给出的属性文件中数据源的格式为:

[plain] 
#连接数据库地址,该地址可动态添加,“link.”之后,“.jdbc”之前的名称为数据库连接池的名称,其余连接池属性如果不写,将自动继承Hummer的数据库连接池配置 
link.eagle2.business.jdbc.jdbcUrl=jdbc:oracle:thin:@192.168.0.155:1521:orcl 
link.eagle2.business.jdbc.user=eagle2 
link.eagle2.business.jdbc.password=eagle2_password 
link.eagle2.interface.jdbc.jdbcUrl=jdbc:oracle:thin:@192.168.0.155:1521:interface 
link.eagle2.interface.jdbc.user=interface 
link.eagle2.interface.jdbc.password=interface22 
link.eagle2.ods.jdbc.jdbcUrl=jdbc:oracle:thin:@192.168.0.10:1521:sifen 
link.eagle2.ods.jdbc.user=honghe 
link.eagle2.ods.jdbc.password=honghe_pwd 

为实现这个要求,我经过google搜索,写代码尝试,最后终于较好的实现了该功能,结果记录如下:
实现一个实现ApplicationContextAware和ApplicationListener接口的类DynamicDataSourceC3p0,实现ApplicationContextAware是为了得到ApplicationContext,实现了ApplicationListener是为了配置spring的加载事件。
类的实现代码如下:
[java] 
import java.io.IOException; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 
 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanDefinition; 
import org.springframework.beans.factory.support.ChildBeanDefinition; 
import org.springframework.beans.factory.support.DefaultListableBeanFactory; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 
import org.springframework.context.ApplicationEvent; 
import org.springframework.context.ApplicationListener; 
import org.springframework.context.event.ContextRefreshedEvent; 
import org.springframework.core.io.support.ResourcePropertySource; 
 
import com.mchange.v2.c3p0.ComboPooledDataSource; 
 
public class DynamicDataSourceC3p0 implements ApplicationContextAware,ApplicationListener { 
 
    private ApplicationContext app; 
    @Override 
    public void setApplicationContext(ApplicationContext app) 
            throws BeansException { 
        this.app = app; 
    } 
    public void onApplicationEvent(ApplicationEvent event) {   
        //如果是容器刷新事件   
        if(event instanceof ContextRefreshedEvent ){//如果是容器关闭事件   
            try { 
                regDynamicBean(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
            //System.out.println(event.getClass().getSimpleName()+" 事件已发生!"); 
        } 
    }   
 
    private void regDynamicBean() throws IOException{ 
        // 解析属性文件,得到数据源Map 
        Map<String, DataSourceInfo> mapCustom = parsePropertiesFile("hummer.properties"); 
        // 把数据源bean注册到容器中 
        addSourceBeanToApp(mapCustom); 
         
    } 
    /**
     * 功能说明:根据DataSource创建bean并注册到容器中
     * @param acf
     * @param mapCustom
     */ 
    private void addSourceBeanToApp(Map<String, DataSourceInfo> mapCustom) { 
        DefaultListableBeanFactory acf = (DefaultListableBeanFactory) app.getAutowireCapableBeanFactory(); 
        BeanDefinition beanDefinition; 
        Iterator<String> iter = mapCustom.keySet().iterator(); 
        while(iter.hasNext()){ 
            String beanKey = iter.next(); 
            // 得到Bean定义,并添加到容器中 
            beanDefinition = new ChildBeanDefinition("dataSource"); 
            // 注意:必须先注册到容器中,再得到Bean进行修改,否则数据源属性不能有效修改 
            acf.registerBeanDefinition(beanKey, beanDefinition); 
            // 再得到数据源Bean定义,并修改连接相关的属性 
            ComboPooledDataSource cpds = (ComboPooledDataSource)app.getBean( beanKey);; 
 
            cpds.setJdbcUrl(mapCustom.get(beanKey).connUrl); 
            cpds.setUser(mapCustom.get(beanKey).userName); 
            cpds.setPassword(mapCustom.get(beanKey).password); 
        } 
    } 
    /**
     * 功能说明:解析属性文件,得到数据源Map
     * @return
     * @throws IOException
     */ 
    private Map<String, DataSourceInfo> parsePropertiesFile(String fileName) throws IOException { 
        // 属性文件 
        ResourcePropertySource props =  new ResourcePropertySource(fileName); 
         
        Matcher matcher; 
        Pattern pattern = Pattern.compile("^link\\.(eagle2\\.\\w+)\\.jdbc\\.(jdbcUrl|user|password)$"); 
         
        Map<String, DataSourceInfo> mapDataSource = new HashMap&

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,