SSM多数据源配置 Day15 2018-12-03

SSM多数据源配置

一、基本配置

1. 数据源配置

<?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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
               http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"
    default-autowire="byName">

    <!-- db配置目录 -->
    <context:property-placeholder file-encoding="utf-8" location="classpath:db.properties" />
   
    <bean id="peisDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${peis.driver}" />
        <property name="jdbcUrl" value="${peis.jdbcUrl}" />
        <property name="user" value="${peis.user}" />
        <property name="password" value="${peis.password}" />
    </bean>
    <bean id="mobileHealthDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${mobileHealth.driver}" />
        <property name="jdbcUrl" value="${mobileHealth.jdbcUrl}" />
        <property name="user" value="${mobileHealth.user}" />
        <property name="password" value="${mobileHealth.password}" />
    </bean>
    
</beans>

2. 定义一个类实现数据库切换的类

定义一个类DynamicDataSource继承AbstractRoutingDataSource实现determineCurrentLookupKey方法,实现数据库切换。

  • DynamicDataSource.java
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {
    /**
     * 返回当前数据源的key值
     */
    @Override
    protected Object determineCurrentLookupKey() {
        System.out.println("getDataSource: " + DynamicDataSourceHolder.getDatasource());
        return DynamicDataSourceHolder.getDatasource();
    }

}
  • 说明:使用SpringAbstractRoutingDataSource类来进行拓展多数据源。

该类就相当于一个dataSource的路由,用于根据key值来进行切换对应的dataSource。可以看到其中获取链接的方法getConnection()调用的determineTargetDataSource是关键方法。该方法用于返回我们使用的数据源。其中又是determineCurrentLookupKey()方法来返回当前数据源的key值。之后通过该key值在resolvedDataSources这个map中找到对应的value(该value就是数据源)。resolvedDataSources这个map则是在:afterPropertiesSet() 这个方法中通过targetDataSources这个map来进行赋值的。我们在配置文件中进行会对targetDataSources赋值:

<bean id="dynamicDataSource" class="com.zhougl.mobilehealth.util.DynamicDataSource">  
        <property name="targetDataSources">  
            <map key-type="java.lang.String">  
                <entry key="peisDataSource" value-ref="peisDataSource"></entry>  
                <entry key="mobileHealthDataSource" value-ref="mobileHealthDataSource"></entry>  
            </map>  
        </property>  
        <property name="defaultTargetDataSource" ref="peisDataSource"></property>  
    </bean> 

3. 定义动态切换数据源的工具类

  • DynamicDataSourceHolder.java
public class DynamicDataSourceHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

    /**
     * 参数为要切换的数据源名称
     * 
     * @param dastsource
     */
    public static void setDatasource(String datasource) {
        System.out.println("setDataSource:  " + datasource);
        contextHolder.set(datasource);
    }

    /**
     * 通过线程的方式获取数据源,目的是为了在并发的情况下依然能够正常切换
     * 
     * @return 线程
     */
    public static String getDatasource() {

        return (String) contextHolder.get();
    }

    /**
     * 用于关闭当前切换的数据源
     */
    public static void clearDatasource() {
        contextHolder.remove();
    }

}

使用了ThreadLocal来保存了数据源:解密ThreadLocal

4. 动态数据源、事务配置

 <!-- 自动装配Bean -->
<context:component-scan base-package="com.zhougl"/>
<!-- 强制使用CGLIB代理 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="dynamicDataSource" class="com.zhougl.mobilehealth.util.DynamicDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry key="peisDataSource" value-ref="peisDataSource"></entry>
                <entry key="mobileHealthDataSource" value-ref="mobileHealthDataSource"></entry>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="peisDataSource"></property>
    </bean>
    <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
    <bean id="DynamicSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dynamicDataSource" />
        <!-- 自动扫描mapping.xml文件 -->
        <property name="mapperLocations" value="classpath*:com/**/*.mapper.xml"></property>
        <!-- pagehelper分页插件拦截器 -->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            helperDialect=oracle
                            reasonable=false
                            supportMethodsArguments=true
                            params=count=countSql
                            autoRuntimeDialect=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>
    <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.**.dao" />
        <property name="sqlSessionFactoryBeanName" value="DynamicSqlSessionFactory" />
    </bean>
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dynamicDataSource" />
    </bean>
    <!-- 拦截器方式配置事物 -->
    <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="modify*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="list*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="seach*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>

    <!-- spring aop事物管理 -->
    <aop:config>
        <aop:pointcut id="transactionPointcut"
            expression="execution(* com.zhougl..service..*.*(..))" />
        <!-- 设置order的值为2,使得数据库事物开启在数据源切换之后,否则数据源切换不会达到效果  -->
        <aop:advisor pointcut-ref="transactionPointcut"
            advice-ref="transactionAdvice" order="2" />
    </aop:config>


二、注解切换数据源(手动切换)

通过注解内容的不同切换数据源,不需要分包,一个service层可以使用多个数据源

1. 定义注解

通过注解的值来获取当前数据源,并进行切换。

  • DataSource.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME) 
public @interface DataSource {
    String value(); 
}

2. 定义数据源动态切换拦截器

  • DynamicDataSourceInterceptor.java
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
/**
 * 数据源动态切换拦截器
 * @author zgldo
 *  设置执行顺序为1,并使用 aop:before 在数据库事物开启前进行数据源切换
 */
public class DynamicDataSourceInterceptor {
    /**
     * 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源 
     * @param point
     * @throws Exception
     */
    public void intercept(JoinPoint point) throws Exception {
        // 获取目标对象的类类型
        Class<?> target = point.getTarget().getClass();
        MethodSignature signature = (MethodSignature) point.getSignature();
        resolveDataSource(target, signature.getMethod());
    }

    /**
     * 提取目标对象方法注解和类型注解中的数据源标识 
     * @param clazz
     * @param method
     */
    private void resolveDataSource(Class<?> clazz, Method method) {
        try {
            Class<?>[] types = method.getParameterTypes();
             // 默认使用类型注解  
            if (clazz.isAnnotationPresent(DataSource.class)) {
                DataSource source = clazz.getAnnotation(DataSource.class);
                DynamicDataSourceHolder.setDatasource(source.value());
                System.out.println("mmmmmmmmmmmmm" + source.value());
            }
            // 方法注解可以覆盖类型注解  
            Method m = clazz.getMethod(method.getName(), types);
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                DataSource source = m.getAnnotation(DataSource.class);
                DynamicDataSourceHolder.setDatasource(source.value());
                System.out.println("nnnnnnnnnnnn" + source.value());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. 配置切面,数据源动态切换

    <!-- 数据源动态切换切面配置 设置执行顺序为1,并使用 aop:before 在数据库事物开启前进行数据源切换 -->
    <aop:config>
        <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor"
            order="1">
            <!-- 拦截所有service实现类的方法 -->
            <aop:pointcut id="dataSourcePointcut"
                expression="execution(* com.zhougl..service..*.*(..))" />
            <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
        </aop:aspect>
    </aop:config>
     <!-- 数据源动态切换实体 -->
    <bean id="dataSourceInterceptor"
        class="com.zhougl.mobilehealth.util.DynamicDataSourceInterceptor" />

4. 完整配置

  • applicationContext.xml
<?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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
               http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"
    default-autowire="byName">
    <!-- 设置AOP代理开启 -->
    <!-- AOP的代理开启放在必须在所有加载的 最前面 -->
    <!-- 强制使用CGLIB代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true" />
    
    <!-- db配置目录 -->
    <context:property-placeholder file-encoding="utf-8" location="classpath:db.properties" />
    
    <bean id="peisDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${peis.driver}" />
        <property name="jdbcUrl" value="${peis.jdbcUrl}" />
        <property name="user" value="${peis.user}" />
        <property name="password" value="${peis.password}" />
    </bean>
    <bean id="mobileHealthDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${mobileHealth.driver}" />
        <property name="jdbcUrl" value="${mobileHealth.jdbcUrl}" />
        <property name="user" value="${mobileHealth.user}" />
        <property name="password" value="${mobileHealth.password}" />
    </bean>
    <bean id="dynamicDataSource" class="com.zhougl.mobilehealth.util.DynamicDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry key="peisDataSource" value-ref="peisDataSource"></entry>
                <entry key="mobileHealthDataSource" value-ref="mobileHealthDataSource"></entry>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="peisDataSource"></property>
    </bean>
    <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
    <bean id="DynamicSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dynamicDataSource" />
        <!-- 自动扫描mapping.xml文件 -->
        <property name="mapperLocations" value="classpath*:com/**/*.mapper.xml"></property>
        <!-- pagehelper分页插件拦截器 -->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            helperDialect=oracle
                            reasonable=false
                            supportMethodsArguments=true
                            params=count=countSql
                            autoRuntimeDialect=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>
    <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.**.dao" />
        <property name="sqlSessionFactoryBeanName" value="DynamicSqlSessionFactory" />
    </bean>
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dynamicDataSource" />
    </bean>
    <!-- 拦截器方式配置事物 -->
    <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="modify*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="list*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="seach*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>

    <!-- spring aop事物管理 -->
    <aop:config>
        <aop:pointcut id="transactionPointcut"
            expression="execution(* com.zhougl..service..*.*(..))" />
        <!-- 设置order的值为2,使得数据库事物开启在数据源切换之后,否则数据源切换不会达到效果  -->
        <aop:advisor pointcut-ref="transactionPointcut"
            advice-ref="transactionAdvice" order="2" />
    </aop:config>

    <!-- 数据源动态切换切面配置 设置执行顺序为1,并使用 aop:before 在数据库事物开启前进行数据源切换 -->
    <aop:config>
        <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor"
            order="1">
            <!-- 拦截所有service实现类的方法 -->
            <aop:pointcut id="dataSourcePointcut"
                expression="execution(* com.zhougl..service..*.*(..))" />
            <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
        </aop:aspect>
    </aop:config>
     <!-- 数据源动态切换实体 -->
    <bean id="dataSourceInterceptor"
        class="com.zhougl.mobilehealth.util.DynamicDataSourceInterceptor" />
</beans>

5. 注解使用示例

  • @DataSource注解是定义在类上
@Service
@DataSource("peisDataSource")
public class UsedDetailServiceImpl implements UsedDetailService {
}
  • @DataSource定义在方法上,方法上定义的注解优先级高于定义在类上的注解
@Service
public class OrderInfoServiceImpl implements OrderInfoService {
    @Autowired
    private OrderInfoDao orderInfoDao;
    @Autowired
    private OrderSetInfoDao orderSetInfoDao;

    @DataSource("mobileHealthDataSource")
    @Override
    public UserInfo getUserInfoById(String userId) {
        UserInfo info = this.orderInfoDao.getUserInfoById(userId);
        return info;
    }

    @DataSource("peisDataSource")
    @Override
    public List<OrderInfo> listOrderInfo(String userId, String peStatus) {
        ...
    }
}

三、分包切换数据源

为每个数据源service层单独建一个包,一个Service只能使用一个数据源。

1. 定义数据源动态切换拦截器

  • DynamicDataSourceInterceptor.java
/**
 * 数据源动态切换拦截器
 * @author zgldo
 *  设置执行顺序为1,并使用 aop:before 在数据库事物开启前进行数据源切换
 */
public class DynamicDataSourceInterceptor {
    /** 切换到数据源1 */
    public void setDataSourceOne() {
        DynamicDataSourceHolder.setDataSource("peisDataSource");
    }
    /** 切换到数据源2 */
 
    public void setDataSourceSecond() { 
      DynamicDataSourceHolder.setDataSource("mobileHealthDataSource"); 
    }
}

2. 配置切面,数据源动态切换

    <!-- 数据源动态切换切面配置 设置执行顺序为1,并使用 aop:before 在数据库事物开启前进行数据源切换 -->
    <aop:config>
        <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor"
            order="1">
            <!-- 拦截所有service实现类的方法 -->
            <aop:pointcut id="dataSourcePointcutOne"
                expression="execution(* com.zhougl.peis..service..*.*(..))" />
            <aop:before pointcut-ref="dataSourcePointcutOne" method="setDataSourceOne" />
            <aop:pointcut id="dataSourcePointcutTwo"
                expression="execution(* com.zhougl.mobile..service..*.*(..))" />
            <aop:before pointcut-ref="dataSourcePointcutTwo" method="setDataSourceSecond" />
        </aop:aspect>
    </aop:config>
     <!-- 数据源动态切换实体 -->
    <bean id="dataSourceInterceptor"
        class="com.zhougl.mobilehealth.util.DynamicDataSourceInterceptor" />

4. 完整配置

  • applicationContext.xml
<?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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
               http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"
    default-autowire="byName">
    <!-- 设置AOP代理开启 -->
    <!-- AOP的代理开启放在必须在所有加载的 最前面 -->
    <!-- 强制使用CGLIB代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true" />
    
    <!-- db配置目录 -->
    <context:property-placeholder file-encoding="utf-8" location="classpath:db.properties" />
    
    <bean id="peisDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${peis.driver}" />
        <property name="jdbcUrl" value="${peis.jdbcUrl}" />
        <property name="user" value="${peis.user}" />
        <property name="password" value="${peis.password}" />
    </bean>
    <bean id="mobileHealthDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${mobileHealth.driver}" />
        <property name="jdbcUrl" value="${mobileHealth.jdbcUrl}" />
        <property name="user" value="${mobileHealth.user}" />
        <property name="password" value="${mobileHealth.password}" />
    </bean>
    <bean id="dynamicDataSource" class="com.zhougl.mobilehealth.util.DynamicDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry key="peisDataSource" value-ref="peisDataSource"></entry>
                <entry key="mobileHealthDataSource" value-ref="mobileHealthDataSource"></entry>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="peisDataSource"></property>
    </bean>
    <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
    <bean id="DynamicSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dynamicDataSource" />
        <!-- 自动扫描mapping.xml文件 -->
        <property name="mapperLocations" value="classpath*:com/**/*.mapper.xml"></property>
        <!-- pagehelper分页插件拦截器 -->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            helperDialect=oracle
                            reasonable=false
                            supportMethodsArguments=true
                            params=count=countSql
                            autoRuntimeDialect=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>
    <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.**.dao" />
        <property name="sqlSessionFactoryBeanName" value="DynamicSqlSessionFactory" />
    </bean>
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dynamicDataSource" />
    </bean>
    <!-- 拦截器方式配置事物 -->
    <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="modify*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="list*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="seach*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>

    <!-- spring aop事物管理 -->
    <aop:config>
        <aop:pointcut id="transactionPointcut"
            expression="execution(* com.zhougl..service..*.*(..))" />
        <!-- 设置order的值为2,使得数据库事物开启在数据源切换之后,否则数据源切换不会达到效果  -->
        <aop:advisor pointcut-ref="transactionPointcut"
            advice-ref="transactionAdvice" order="2" />
    </aop:config>

    <!-- 数据源动态切换切面配置 设置执行顺序为1,并使用 aop:before 在数据库事物开启前进行数据源切换 -->
    <aop:config>
        <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor"
            order="1">
            <!-- 拦截所有service实现类的方法 -->
            <!-- 配置数据源一 -->
            <aop:pointcut id="dataSourcePointcutOne"
                expression="execution(* com.zhougl.peis..service..*.*(..))" />
            <aop:before pointcut-ref="dataSourcePointcutOne" method="setDataSourceOne" />
            <!-- 配置数据源二 -->
            <aop:pointcut id="dataSourcePointcutTwo"
                expression="execution(* com.zhougl.mobile..service..*.*(..))" />
            <aop:before pointcut-ref="dataSourcePointcutTwo" method="setDataSourceSecond" />
        </aop:aspect>
    </aop:config>
     <!-- 数据源动态切换实体 -->
    <bean id="dataSourceInterceptor"
        class="com.zhougl.mobilehealth.util.DynamicDataSourceInterceptor" />
</beans>

  • 另一种方法:通过aop的after,before的配置拦截器,在拦截器的before方法里,通过获取模板对象的类名来获取所在包名,不同的包配置不同的数据源。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,678评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,833评论 6 342
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,222评论 25 707
  • 时间总是在过去之后显得飞快,一转眼又到月底。这是2018年的第9篇月度小结,是第20篇月度总结。 从决心每个月写总...
    申湘黔阅读 772评论 2 2
  • 我爱我的简化 我爱这简化 一条线,一个点 一刀伤口 我很简单 躺着就是躺着 身体和天空平行 丁丁和天空垂直 我很害...
    一首诗和小H阅读 149评论 0 0