主要配置:
<?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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 启动扫描component功能 --> <context:component-scan base-package="com.tch.test.springmvcmybatis" /> <!-- viewResolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/" /> <property name="suffix" value=".jsp" /> </bean> <mvc:annotation-driven /> <!-- 拦截器 --> <!-- <mvc:interceptors> 这里配置的拦截器相当于全局拦截器,只要有响应的后端处理器,就会经过该拦截器 <bean class="com.tch.test.springmvcmybatis.interceptor.MyInteceptor" /> <mvc:interceptor> 只拦截匹配的路径 <mvc:mapping path="/namespace/*" /> <bean class="com.tch.test.springmvcmybatis.interceptor.MyInteceptor2" /> </mvc:interceptor> </mvc:interceptors> --> <!-- 启动注解实物配置功能 --> <!-- <tx:annotation-driven transaction-manager="transactionManager" /> --> <!-- 数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/test"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 数据源(slave) --> <bean id="slave_dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/test_slave"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <bean id="dynamicDataSource" class="com.tch.test.springmvcmybatis.datasource.DynamicDataSource"> <property name="targetDataSources"> <map> <entry key="slave" value-ref="slave_dataSource" /> </map> </property> <property name="defaultTargetDataSource" ref="dataSource" /> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dynamicDataSource" /> </bean> <bean id="chooseDataSourceAdvice" class="com.tch.test.springmvcmybatis.datasource.ChooseDataSource"></bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config expose-proxy="true"> <!-- proxy-target-class="true" --> <!-- 只对业务逻辑层实施事务 --> <aop:pointcut id="txPointcut" expression="execution(* com.tch.test.springmvcmybatis.service.*Service.*(..)) AND ! execution(* com.tch.test.springmvcmybatis.service.*Service.get*(..))" /> <aop:pointcut id="determineReadOrWritePointcut" expression="execution(* com.tch.test.springmvcmybatis.service.*Service.get*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" /> <!-- 通过AOP切面实现读/写库选择 --> <aop:aspect order="-2147483648" ref="chooseDataSourceAdvice"> <aop:around pointcut-ref="determineReadOrWritePointcut" method="determineReadOrWriteDB" /> </aop:aspect> </aop:config> <!--读取数据库配置文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dynamicDataSource" /> <!-- 如果mapper的xml文件名字和mapper接口的名字一致,并且在同一目录下(例如UserMapper.java和UserMapper.xml),可以不配置mapperLocations, --> <property name="mapperLocations" value="classpath:mybatis/**/*Mapper.xml" /> <!-- 指定别名,在mapper的xml文件中可以使用别名(例如User/user来代表com.tch.test.spring_mybatis.entity.User),提高开发效率 --> <!-- <property name="typeAliasesPackage" value="com.tch.test.springmvcmybatis.bean" /> --> <property name="configLocation" value="classpath:sqlMapConfig.xml"></property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 指定mapper接口包名,可以通过动态代理生成代理类,这样就可以在service层直接通过注入的方式进行dao操作了 --> <property name="basePackage" value="com.tch.test.springmvcmybatis.mapper" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean> </beans>
说明:
当满足execution(* com.tch.test.springmvcmybatis.service.*Service.get*(..))切面的时候,切面会调用com.tch.test.springmvcmybatis.datasource.ChooseDataSource的determineReadOrWriteDB方法,
这个切面是around的类型,首先通过JdbcContextHolder.setSlave();将当前线程的数据源设为slave,最终获取到的dataSource就是slave_dataSource,从而达到对读操作使用slave_dataSource数据源的目的。
当满足execution(* com.tch.test.springmvcmybatis.service.*Service.*(..)) AND ! execution(* com.tch.test.springmvcmybatis.service.*Service.get*(..))切面的时候,
也就是增删改操作,需要事务,也就需要使用dataSource作为数据源,因为这时候没有调用JdbcContextHolder.setSlave(),此时,com.tch.test.springmvcmybatis.datasource.DynamicDataSource
就会使用默认的数据源defaultTargetDataSource,即dataSource作为数据源,从而达到目的。
这里面要注意的是,transactionManager和sqlSessionFactory都需要使用dynamicDataSource作为数据源,dynamicDataSource会根据determineCurrentLookupKey方法的返回值决定使用哪个数据源(slave_dataSource或者dataSource)
order="-2147483648" 表明优先级最高
相关推荐
spring aop 实现应用层读写分离的,包括一主多从配置使用
我感觉很不错的技术文档,现在和大家分享,希望能够帮到大家,如果你需要可以下载看看,很适合喜欢研究技术的人员
springaop多数据库读写分离
读写分离就是对于一条SQL该选择哪一个数据库去执行,至于谁来做选择数据库这件事,有两个,要么使用中间件帮我们做,要么程序自己做。一般来说,读写分离有两种实现方式。第一种是依靠中间件MyCat,也就是说应用程序...
spring mysql 读写分离,可以一主一从,也可以一主多从
本demo 实现了 spring+mysql+mybatis+springMVC 读写分离 希望对有需要的朋友有帮助如果大家有什么好的意见可以提 互相学习 觉得有用多多点赞哈哈哈!
主要介绍了利用Spring配置动态数据源实现读写分离的方法,文中通过示例代码介绍的很详细,相信对大家的理解和学习具有一定的参考借鉴价值,藕需要的朋友可以一起学习学习。
springBoot+mybatis+AOP实现读写分离,在代码层面直接实现,无需任何插件,简单易懂,非常适合作为解决数据库并发大的解决方案
在应用层通过spring特性解决数据库读写分离代码
spring+springmvc+mybatis的整合以及数据库读写分离的测试
通过spring实现的读写分离例子 当然,需要提前在db层配置好mysql的主从配置 mysql主从配置:http://blog.csdn.net/u013614451/article/details/48901541
springboot+mybatis+mysql实现读写分离 先在建好mysql主从数据库的配置,然后在代码中根据读写分离或强制读取master数据库中的数据 mysql数据库设置主从,参考: ...
springboot+mybatis+druid+redis实现数据库读写分离和缓存
Mybatis读写分离,支持n多的从库,简单的负载均衡。数据库是mysql,采用druid连接池。 读写分离采用插件的形式实现的,优点是不需要写源注解,不需要写分开的Mapper.xml。 如果只有主库的话,那么会创建两个地址相同...
Spring实现数据库读写分离/spring事务配置解释(Annotation/Spring AOP/Reflection)的辅助sql
spring +springboot+mybatis+maven 读写分离,数据库采用mysql, 采用springboot 采用项目框架搭建,继承spring 中的AbstractRoutingDataSource,实现 determineCurrentLookupKey 进行数据源的动态切换,采用Spring ...
实现mysql读写分离+使用视频
maven+ssm(spring,springmvc,mybatis)+读写分离的demo,读写分离是动态选取数据源
通过 sprigboot 搭建mysql读写分离 mysql服务器需搭建主从复制