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

#连接数据库地址,该地址可动态添加,“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
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<String,DataSourceInfo>();
        // 根据配置文件解析数据源
        for(String keyProp : props.getPropertyNames())
        {
            matcher = pattern.matcher(keyProp);
            if(matcher.find()){
                String dsName = matcher.group(1);
                String dsPropName = matcher.group(2);
                DataSourceInfo dsi;
                
                if(mapDataSource.containsKey(dsName)){
                    dsi = mapDataSource.get(dsName);
                }
                else{
                    dsi = new DataSourceInfo();
                }
                // 根据属性名给数据源属性赋值
                if("jdbcUrl".equals(dsPropName)){
                    dsi.connUrl = (String)props.getProperty(keyProp);
                }else if("user".equals(dsPropName)){
                    dsi.userName = (String)props.getProperty(keyProp);
                }else if("password".equals(dsPropName)){
                    dsi.password = (String)props.getProperty(keyProp);
                }
                mapDataSource.put(dsName, dsi);
            }
        }
        return mapDataSource;
    }
    
    private class DataSourceInfo{
        public String connUrl;
        public String userName;
        public String password;
        
        public String toString(){
            
            return "(JcbcUrl:"+connUrl+", user:"+userName+", password:"+password+")";
        }
    }
}

acf.registerBeanDefinition不用判断容器中是否已经有相应名字的bean,spring会在该名称的bean存在时覆盖,

不存在时添加。

转载于:https://my.oschina.net/u/1183665/blog/517931

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值