`

<转>Spring AOP根据JdbcTemplate方法名动态设置数据源

 
阅读更多

转载: Spring AOP根据JdbcTemplate方法名动态设置数据源

http://blog.csdn.net/yubaoma2014/article/details/12427885
作者: yubaoma2014

 

有删节.

 

目的: 

1. 配置多个数据源

2. 根据不同的数据源执行不同的数据操作方法

3. 事务管理?

 

  • 多数据源配置
        <!-- 主数据源, 用于执行写入操作 -->
        <bean id="masterDataSource"
            class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="driverClassName"
                value="${jdbc.driverClassName}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <property name="poolPreparedStatements" value="true" />
            <property name="defaultAutoCommit" value="true" />
        </bean>
        <!-- 从数据源, 用于执行查询操作 -->
        <bean id="slaveDataSource"
            class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="driverClassName"
                value="${jdbc.driverClassName}" />
            <property name="url" value="${jdbc.url2}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <property name="poolPreparedStatements" value="true" />
            <property name="defaultAutoCommit" value="true" />
        </bean>
    
        <!-- 动态数据源 -->
        <bean id="dataSource"
            class="test.my.serivce.ds.DynamicDataSource">
            <!-- 配置一个数据源Map, 注意这里的key值, 后面很多地方都使用到 -->
            <property name="targetDataSources">
                <map>
                    <entry key="master" value-ref="masterDataSource" />
                    <entry key="slave" value-ref="slaveDataSource" />
                </map>
            </property>
            <!-- 动态数据源默认使用的数据源 -->
            <property name="defaultTargetDataSource" ref="masterDataSource" />
        </bean>
    
    <!-- 配置JdbcTemplate -->
    <bean id="jdbcTemplate"
            class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean>
    BEAN "dataSource" 是自定义类DynamicDataSource的一个实例, 而DynamicDataSource则是继承了Spring的抽象类AbstractRoutingDataSource, 顾名思义, 这是一个数据源的路由/查找类.
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    // 自定义类
    public class DynamicDataSource extends AbstractRoutingDataSource {
        
        @Override
        // 返回当前需要使用的数据源的key
        protected Object determineCurrentLookupKey() {
            // 
            return CustomerContextHolder.getCustomerType();
        }
    }
     
    //  AbstractRoutingDataSource 的部分源码
    
    public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
            
            // 重写了 getConnection() 方法
         	@Override
    	public Connection getConnection() throws SQLException {
    		return determineTargetDataSource().getConnection();
    	}
    
            // 设置当前使用的目标数据源
    	protected DataSource determineTargetDataSource() {
    		Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
                    // 目标数据源的key.
    		Object lookupKey = determineCurrentLookupKey();
                    // 获取数据源
    		DataSource dataSource = this.resolvedDataSources.get(lookupKey);
    		if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
    			dataSource = this.resolvedDefaultDataSource;
    		}
    		if (dataSource == null) {
    			throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
    		}
    		return dataSource;
    	}
            
            // 抽象方法, 返回目标数据源对应的key
            // 这里的key对应于在BEAN "dataSource"中配置的属性"targetDataSources"中的key
            protected abstract Object determineCurrentLookupKey();
    }
     
    // CustomerContextHolder, 一个ThreadLocal实现, 用于管理key
    // ThreadLocal是线程安全的, 且线程之间不能共享
    public class CustomerContextHolder {
        private static final ThreadLocal contextHolder = new ThreadLocal();
        public static void setCustomerType(String customerType) {
            contextHolder.set(customerType);
        }
        public static String getCustomerType() {
            return (String) contextHolder.get();
        }
        public static void clearCustomerType() {
            contextHolder.remove();
        }
    }
     
  • 利用AOP, 实现不同的数据源执行不同的数据操作方法
        <bean id="ba" class="test.my.serivce.ds.BeforeAdvice" />
        <!-- 强制使用CGLIB代理 -->
        <aop:config proxy-target-class="true">
    
            <!-- 切面一 主数据源执行写入操作 -->
            <aop:aspect ref="ba">
                <!-- 切点, 与数据库update相关的函数 -->
                <aop:pointcut id="update"
                    expression="execution(* org.springframework.jdbc.core.JdbcTemplate.update*(..)) || execution(* org.springframework.jdbc.core.JdbcTemplate.batchUpdate(..))" />
                <!-- 前置通知, 执行数据源设置操作 -->
                <aop:before method="setMasterDataSource"
                    pointcut-ref="update" />
            </aop:aspect>
    
            <!-- 切面二 从数据源执行查询操作 -->
            <aop:aspect ref="ba">
                <aop:before method="setSlaveDataSource"
                    pointcut="execution(* org.springframework.jdbc.core.JdbcTemplate.query*(..)) || execution(* org.springframework.jdbc.core.JdbcTemplate.execute(..))" />
            </aop:aspect>
        </aop:config>
        
     BEAN "ba"相关的类
    public class BeforeAdvice {
        public void setMasterDataSource() {
            CustomerContextHolder.setCustomerType("master");
        }
        public void setSlaveDataSource() {
            CustomerContextHolder.setCustomerType("slave");
        }
    }
     
分享到:
评论

相关推荐

    springAop多数据源

    总结来说,"springAop多数据源"项目涉及到Spring框架的多数据源配置、JdbcTemplate的使用、面向切面编程的应用,以及使用JUnit进行测试。理解并掌握这些技术对于构建灵活、可扩展的Java应用程序至关重要。在实践中,...

    4.Spring中的JdbcTemplate,Spring中的的事务,

    &lt;bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"&gt; &lt;property name="dataSource" ref="dataSource"/&gt; &lt;/bean&gt; ``` #### Spring中配置数据源 Spring支持多种数据源的配置,包括C3P0、...

    java Spring JdbcTemplate 入门工具

    2. 配置Bean:在Spring的配置文件中,定义一个名为`jdbcTemplate`的Bean,注入上面创建的数据源。 ```xml &lt;bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"&gt; &lt;property ...

    day4-Spring JdbcTemplate & 声明式事务.md

    3. **创建JdbcTemplate对象**:在Spring配置文件中定义数据源和JdbcTemplate bean。数据源负责连接数据库,而JdbcTemplate则用于执行SQL语句。 ```xml &lt;!-- 在Spring配置文件中定义数据源 --&gt; &lt;bean id=...

    SpringJDBC.rar_SpringJDBC_jdbctemplate_jdbctemplate spring

    - **配置JdbcTemplate**:在Spring配置文件中声明一个JdbcTemplate实例,并注入数据源。 - **执行SQL查询**:使用`query(String sql, RowMapper&lt;T&gt; rowMapper)`方法执行SQL查询,`RowMapper`接口用于将结果集中的...

    spring-jdbcTemplate实例工程

    3. **测试友好**:支持模拟数据源,便于单元测试。 4. **适用场景**:适用于简单到中等复杂的数据库操作,如CRUD(创建、读取、更新、删除)操作,但不适合高度复杂的SQL逻辑。 总的来说,Spring JdbcTemplate是...

    动态数据源实现spring

    在Spring框架中,动态数据源实现是一个重要的特性,它允许应用程序根据特定的条件或用户需求在运行时切换数据源。这种灵活性对于多租户系统、数据隔离或者在不同环境(如开发、测试、生产)之间切换数据库配置尤其...

    Spring 通过连接mysql,通过JdbcTemplate和SimpleJdbcTemplate来操作数据库

    1. 创建数据源:数据源是数据库连接的来源,Spring支持多种类型的数据源,如`BasicDataSource`。 2. 创建`JdbcTemplate`实例:通过数据源实例化`JdbcTemplate`对象。 3. 执行SQL:使用`JdbcTemplate`的方法执行SQL,...

    spring+mybatis 多个数据源调用示例

    Spring提供了一种基于AOP(面向切面编程)的方式来处理多数据源的切换。我们可以通过在Service层的方法上添加注解,指定使用哪个数据源。例如,使用`@Transactional`注解并配合`@Qualifier`来指定数据源: ```java ...

    spring.zip

    Spring框架是Java开发中广泛应用的一个...通过配置数据源、使用`JdbcTemplate`工具类以及事务管理,我们可以轻松地完成数据库的增删改查任务。对于初学者来说,理解并掌握这些知识是进阶为高级Java开发者的关键步骤。

    spring WEB入门级项目搭建

    以上代码只是一个简化的示例,实际项目中,你需要根据实际情况调整代码,例如添加数据源配置、使用连接池、实现更复杂的用户验证逻辑等。在`chapter2`中,可能包含了项目结构、详细代码和其他相关资源,这些都可以...

    spring mvc+jdbctemplate非注解例子

    接下来,JdbcTemplate的使用意味着你需要配置数据源和JdbcTemplate实例。数据源是连接数据库的工厂,通常可以使用连接池如Apache Commons DBCP或C3P0来实现。在XML配置中,你会看到如何定义数据源,然后创建一个bean...

    spring1.2 操作多个数据源

    // 在这里,jdbcTemplate会根据MyRoutingDataSource的设置自动选择合适的数据源 public void performOperation(String operation) { // ... } } ``` 四、注意事项 4. 配置事务管理: 当涉及到事务管理时,确保...

    Spring boot +jdbctemplate

    - **配置**:Spring Boot通过`spring.datasource`配置项来设置数据源,支持多种类型的数据源,如HikariCP、Tomcat JDBC等。 - **连接池**:使用连接池如HikariCP可以有效地管理数据库连接,提高应用性能。 - **...

    spring applicationContext 配置文件

    &lt;?xml version="1.0" encoding="UTF-... &lt;bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"&gt; &lt;property name="dataSource"&gt;&lt;ref bean="dataSourceProxy"/&gt;&lt;/property&gt; &lt;/bean&gt; &lt;/beans&gt;

    Spring Boot 动态数据源文檔

    ### Spring Boot 动态数据源实现详解 #### 概述 Spring Boot 动态数据源是一种常见的企业级应用需求,特别是在需要支持多个不同数据库的情况下。本文档将详细介绍如何在Spring Boot项目中实现动态数据源的配置与...

    java spring 多数据源

    - 使用Spring AOP来实现数据源的动态切换。创建一个切面类,如`DataSourceAspect`,其中定义一个环绕通知方法`@Around("execution(* com.example..service.*.*(..))")`,该方法将在所有Service层的方法执行前后被...

    spring-springMvc-jdbctemplate.rar

    开发者可能需要配置Spring的数据源(DataSource)来连接Oracle数据库,并使用JdbcTemplate进行数据操作。 另外,项目还引入了Redis,一个内存中的数据结构存储系统,常被用作数据库、缓存和消息中间件。在Web应用中...

    struts2.3.4+spring3.1.1+jdbctemplate

    这两个配置文件需要正确地集成,确保Action类能够被Spring容器管理,并且JdbcTemplate的相关配置(如数据源、事务管理器)也应完整无误。 在实际应用中,这样的组合提供了灵活的架构和高效的数据库访问。Struts2...

    HibernateSpring多数据库解决方案.doc

    在IT行业中,尤其是在Java开发领域,使用Spring框架与Hibernate整合是常见的做法,它们可以提供高效的数据访问和...同时,根据业务需求,可能还需要动态切换数据源,这通常通过AOP(面向切面编程)或自定义拦截器实现。

Global site tag (gtag.js) - Google Analytics