转载: 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多数据源"项目涉及到Spring框架的多数据源配置、JdbcTemplate的使用、面向切面编程的应用,以及使用JUnit进行测试。理解并掌握这些技术对于构建灵活、可扩展的Java应用程序至关重要。在实践中,...
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> ``` #### Spring中配置数据源 Spring支持多种数据源的配置,包括C3P0、...
2. 配置Bean:在Spring的配置文件中,定义一个名为`jdbcTemplate`的Bean,注入上面创建的数据源。 ```xml <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"> <property ...
3. **创建JdbcTemplate对象**:在Spring配置文件中定义数据源和JdbcTemplate bean。数据源负责连接数据库,而JdbcTemplate则用于执行SQL语句。 ```xml <!-- 在Spring配置文件中定义数据源 --> <bean id=...
- **配置JdbcTemplate**:在Spring配置文件中声明一个JdbcTemplate实例,并注入数据源。 - **执行SQL查询**:使用`query(String sql, RowMapper<T> rowMapper)`方法执行SQL查询,`RowMapper`接口用于将结果集中的...
3. **测试友好**:支持模拟数据源,便于单元测试。 4. **适用场景**:适用于简单到中等复杂的数据库操作,如CRUD(创建、读取、更新、删除)操作,但不适合高度复杂的SQL逻辑。 总的来说,Spring JdbcTemplate是...
在Spring框架中,动态数据源实现是一个重要的特性,它允许应用程序根据特定的条件或用户需求在运行时切换数据源。这种灵活性对于多租户系统、数据隔离或者在不同环境(如开发、测试、生产)之间切换数据库配置尤其...
1. 创建数据源:数据源是数据库连接的来源,Spring支持多种类型的数据源,如`BasicDataSource`。 2. 创建`JdbcTemplate`实例:通过数据源实例化`JdbcTemplate`对象。 3. 执行SQL:使用`JdbcTemplate`的方法执行SQL,...
Spring提供了一种基于AOP(面向切面编程)的方式来处理多数据源的切换。我们可以通过在Service层的方法上添加注解,指定使用哪个数据源。例如,使用`@Transactional`注解并配合`@Qualifier`来指定数据源: ```java ...
Spring框架是Java开发中广泛应用的一个...通过配置数据源、使用`JdbcTemplate`工具类以及事务管理,我们可以轻松地完成数据库的增删改查任务。对于初学者来说,理解并掌握这些知识是进阶为高级Java开发者的关键步骤。
以上代码只是一个简化的示例,实际项目中,你需要根据实际情况调整代码,例如添加数据源配置、使用连接池、实现更复杂的用户验证逻辑等。在`chapter2`中,可能包含了项目结构、详细代码和其他相关资源,这些都可以...
接下来,JdbcTemplate的使用意味着你需要配置数据源和JdbcTemplate实例。数据源是连接数据库的工厂,通常可以使用连接池如Apache Commons DBCP或C3P0来实现。在XML配置中,你会看到如何定义数据源,然后创建一个bean...
// 在这里,jdbcTemplate会根据MyRoutingDataSource的设置自动选择合适的数据源 public void performOperation(String operation) { // ... } } ``` 四、注意事项 4. 配置事务管理: 当涉及到事务管理时,确保...
- **配置**:Spring Boot通过`spring.datasource`配置项来设置数据源,支持多种类型的数据源,如HikariCP、Tomcat JDBC等。 - **连接池**:使用连接池如HikariCP可以有效地管理数据库连接,提高应用性能。 - **...
<?xml version="1.0" encoding="UTF-... <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"><ref bean="dataSourceProxy"/></property> </bean> </beans>
### Spring Boot 动态数据源实现详解 #### 概述 Spring Boot 动态数据源是一种常见的企业级应用需求,特别是在需要支持多个不同数据库的情况下。本文档将详细介绍如何在Spring Boot项目中实现动态数据源的配置与...
- 使用Spring AOP来实现数据源的动态切换。创建一个切面类,如`DataSourceAspect`,其中定义一个环绕通知方法`@Around("execution(* com.example..service.*.*(..))")`,该方法将在所有Service层的方法执行前后被...
开发者可能需要配置Spring的数据源(DataSource)来连接Oracle数据库,并使用JdbcTemplate进行数据操作。 另外,项目还引入了Redis,一个内存中的数据结构存储系统,常被用作数据库、缓存和消息中间件。在Web应用中...
这两个配置文件需要正确地集成,确保Action类能够被Spring容器管理,并且JdbcTemplate的相关配置(如数据源、事务管理器)也应完整无误。 在实际应用中,这样的组合提供了灵活的架构和高效的数据库访问。Struts2...
在IT行业中,尤其是在Java开发领域,使用Spring框架与Hibernate整合是常见的做法,它们可以提供高效的数据访问和...同时,根据业务需求,可能还需要动态切换数据源,这通常通过AOP(面向切面编程)或自定义拦截器实现。