转载: 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"); } }
相关推荐
spring jdbcTemplate 多数据源切换数据库操作,junit测试。
<?xml version="1.0" encoding="UTF-... <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"><ref bean="dataSourceProxy"/></property> </bean> </beans>
9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知事务操作 9.5.9. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用TransactionTemplate 9.6.2. ...
Spring Data JDBC 提供了多种 JDBC 数据访问解决方案,例如使用 JdbcTemplate、使用 Spring Data JDBC 等。 15. Spring Data JPA Spring Data JPA 是指使用 Spring 框架的 JPA 数据访问层,帮助开发者快速构建数据...
Spring入门学习笔记,内容包括Spring介绍,Spring配置文件,Spring配置数据源,Spring的注解开发,Spring集成Junit,Spring的AOP,jdbcTemplate介绍,Spring控制事务流程,Spring集成web。
8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础知识 9.1.1 何为数据库事务 9.1.2 数据并发的问题 9.1.3 数据库锁机制 9.1.4 事务隔离级别 9.1.5 JDBC对事务支持 9.2 ThreadLocal...
6、Spring数据源集成配置 7、Spring注解开发 8、Spring集成Junit测试 9、Spring集成web环境 10、Spring JDBCTemplate基本使用 11、SpringAOP简介和快速入门 12、Spring XML方式配置AOP 13、Spring注解方式配置AOP 14...
9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.6.1. @Transactional 有关的设置 9.5.7. 插入事务操作 9.5.8. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用 ...
8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础知识 9.1.1 何为数据库事务 9.1.2 数据并发的问题 9.1.3 数据库锁机制 9.1.4 事务隔离级别 9.1.5 JDBC对事务支持 9.2 ThreadLocal...
--多种数据源的配置、JdbcTemplate、事务的处理 20 Spring Boot AOP 21 Spring Boot Starter18:31 --快速构建自定义的Spring Boot Starter 22 Spring Boot 日志30:58 --演示了如何在Spring Boot里面使用日志配置...
Spring Boot JdbcTemplate配置Druid多数据源 Spring Boot AOP记录用户操作日志 Spring Boot中使用thymeleaf Spring Boot中使用Redis缓存数据 Spring Boot中使用Ehcache缓存数据 Spring Boot中的JSON技术 Spring Boot...
9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用 TransactionTemplate 9.6.2. 使用 ...
9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知事务操作 9.5.9. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用TransactionTemplate 9.6.2. ...
9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用 TransactionTemplate 9.6.2. 使用 ...
- chapter3-2-4:[多数据源配置(二):Spring-data-jpa](http://blog.didispace.com/springbootmultidatasource/) - chapter3-2-5:[使用NoSQL数据库(一):Redis](http://blog.didispace.com/springbootredis/) -...
ElasticSearch(基本操作和高级查询)、Async(异步任务)、集成Dubbo(采用官方的starter)、MongoDB(文档数据库)、neo4j(图数据库)、docker(容器化)...第三方登录)、LDAP(增删改查)、动态添加/切换数据源、单机限流(AOP +...
要使用声明式事务,需要先搭建环境,包括导入相关依赖、配置数据源和 JdbcTemplate、给方法上标注 @Transactional、开启基于注解的事务管理功能、配置事务管理器等步骤。 1. 导入相关依赖:需要导入 Spring-jdbc ...
ElasticSearch(`基本操作和高级查询`)、Async(`异步任务`)、集成Dubbo(`采用官方的starter`)、MongoDB(`文档数据库`)、neo4j(`图数据库`)、docker...登录`)、LDAP(`增删改查`)、`动态添加/切换数据源`、单机限流(`AOP +...
chapter3-2-4:多数据源配置(二):Spring-data-jpa chapter3-2-5:使用NoSQL数据库(一):Redis chapter3-2-6:使用NoSQL数据库(二):MongoDB chapter3-2-7:整合MyBatis chapter3-2-8:MyBatis注解配置详解 ...
Redis jwt mybatis / jdbcTemplate任选定时任务内置用户-角色-权限控制多角色免重登切换模块标签页切换免刷新AOP实现多数据源动态切换(分支:multi-datasource)运行截图说明如有任何问题欢迎在问题中讨论