Spring 父子容器使用实例

今天被问到一个有意思的问题,就是通过固定的数据源A,动态产生数据源B。其实就是在properties文件中配置数据源A,然后把数据源B用占位。把数据源A查询到的数据动态的替换给数据源B的占位符。知道Spring IOC初始化的小伙伴都知道。替换占位符操作是的操作是在Spring 对象实例化之前进行的。所以常规方法就不能进行这样的操作,就只能应用Spring的父子容器。具体可以看org.springframework.beans.factory.HierarchicalBeanFactory这个类。

public interface HierarchicalBeanFactory extends BeanFactory {

    /**
     * 返回当前容器的父容器,如果没有就返回null
     */
    BeanFactory getParentBeanFactory();

    /**
     * 返回当前BeanFactory是否包含名name的bean
     */
    boolean containsLocalBean(String name);

}

典型的应用就是Spring Web MVC:

这里写图片描述

父容器不能使用子容器的bean.而子容器能够使用父容器的bean.

下面我们就是使用这个特性来达到之前的需求。

1、父容器 – parent.xml

定义父容器,提供动态数据库的查询datasource Bean.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <content:property-placeholder location="jdbc.properties" />

    <bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${dataSource1.driverClassName}"/>
        <property name="url" value="${dataSource1.url}" />
    </bean>

</beans>
2、父容器资源文件 – jdbc.properties
dataSource1.driverClassName=org.h2.Driver
dataSource1.url=localhost:h2
3、子容器 – datasource.xml

子容器,使用父容器的dataSource1 这个bean来查询dataSource2这个动态数据源。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean class="com.weimob.carl.user.spring.DataSourcePropertyPlaceholderConfigurer" >
        <property name="dataSource" ref="dataSource1" />
    </bean>

    <bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${dataSource2.driverClassName}" />
        <property name="url" value="${dataSource2.url}" />
    </bean>

</beans>
4、占位符替换类

重写org.springframework.core.io.support.PropertiesLoaderSupport的loadProperties方法来自定义占位符替换。

/**
 * Created by Carl on 2016/9/24.
 */
public class DataSourcePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {

    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    protected void loadProperties(Properties props) throws IOException {
        // 只要能够注入成功就可以使用dataSource查找数据库
        System.out.println("获取动态数据源的dataSource :" + dataSource);
        props.put("dataSource2.driverClassName", "org.h2.Driver");
        props.put("dataSource2.url", "haha");
    }
}
5、Test类
public class Main {

    public static void main(String[] args) {
        ApplicationContext parent = new ClassPathXmlApplicationContext("parent.xml");
        ApplicationContext dataSourceContext = new ClassPathXmlApplicationContext(new String[]{"datasource.xml"}, parent);
        DataSource dataSource = (DataSource) dataSourceContext.getBean("dataSource2");
        System.out.println("动态数据源 : " + dataSource);
    }

}
6、运行结果

这里写图片描述

可以看到实现了动态替换数据源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值