使用Adivisor配置增强处理,来实现数据库读写分离
一、先写一个demo来概述Adivisor的简单使用步骤
实现步骤:
1、通过MethodBeforeAdivice接口实现前置增强处理
public class ServiceBeforeAdvisor implements MethodBeforeAdvice {
private Logger logger = Logger.getLogger(ServiceBeforeAdvisor.class);
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
logger.info("启动事务");
logger.info("连接点对象:"+target.getClass().getSimpleName());
logger.info("连接点方法:"+method.getName());
logger.info("连接点方法参数:"+args[0]);
}
}
2、使用<aop:advisor>标签织入增强处理
//注意:advisor要放在aspect前面
<bean id="userService" class="com.pb.service.UserService"></bean>
<bean id="serviceBeforeAdvisor" class="com.pb.aop.ServiceBeforeAdvisor"></bean>
<aop:config>
<aop:pointcut expression="execution(public * com.pb.service.*.*(..))"
id="servicePointcut"/>
<aop:advisor advice-ref="serviceBeforeAdvisor" pointcut-ref="servicePointcut"/>
</aop:config>
3、测试类型
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("applicationContext.xml");
UserService service = (UserService)context.getBean("userService");
service.addUser(new User());
}
}
二、使用Adivisor来实现数据读写分离
实现步骤:
1、通过MethodBeforeAdivice接口实现前置增强处理
public class DataBaseAdvice implements MethodBeforeAdvice {
/**
* 日志计数器
*/
private final static Logger logger = LoggerFactory.getLogger(DataBaseAdvice.class);
/**
* 存储方法前缀
*/
private List<String> methodKey;
/**
* 是否打印日志:true-打印,false-不打印
*/
private boolean showLog = true;
public void before(Method method, Object[] objects, Object o) throws Throwable {
boolean write = true;
String methodName = method.getName().toLowerCase();
//若方法前缀匹配成功,返回false
if (CollectionUtils.isNotEmpty(methodKey)) {
for (String key : methodKey) {
if (methodName.startsWith(key.toLowerCase())) {
write = false;
break;
}
}
}
if (write) {
DbContextHolder.setDbType(DbContextHolder.DB_TYPE_RW);
if (showLog) {
logger.info(method.getName()+"连接主库");
}
}else {
DbContextHolder.setDbType(DbContextHolder.DB_TYPE_R);
if (showLog) {
logger.info(method.getName()+"连接从库");
}
}
}
public List<String> getMethodKey() {
return methodKey;
}
public void setMethodKey(List<String> methodKey) {
this.methodKey = methodKey;
}
public boolean isShowLog() {
return showLog;
}
public void setShowLog(boolean showLog) {
this.showLog = showLog;
}
}
切换主从库的持有类
public class DbContextHolder {
/**
* 线程threadLocal
*/
private static ThreadLocal<String> contextHolder = new ThreadLocal<String>();
/**
* 主库:执行读写操作
*/
public static String DB_TYPE_RW = "dataSourceMaster";
/**
* 从库:执行读库操作
*/
public static String DB_TYPE_R = "dataSourceSlave";
/**
* 默认是读写库
* @return
*/
public static String getDbType() {
String db = contextHolder.get();
if (db == null) {
db = DB_TYPE_RW;
}
return db;
}
/**
* 置本线程的dbType
* @param str
*/
public static void setDbType(String str) {
contextHolder.set(str);
}
/**
* @Title: clearDBType
* @Description: 清理连接类型
*/
public static void clearDBType() {
contextHolder.remove();
}
}
2、使用<aop:advisor>标签织入增强处理
<!-- 动态数据源 -->
<bean id="dynamicDataSource" class="com.alibaba.health.dao.dynamic.DynamicDataSource">
<!-- 通过key-value关联数据源 -->
<property name="targetDataSources">
<map>
<entry value-ref="dataSourceMaster" key="monitorDataSourceMaster"/>
<entry value-ref="dataSourceSlave" key="monitorDataSourceSlave"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceMaster"/>
</bean> <!-- 通知器的具体实现:配置主从库读写分离:以select、query、find、count开头的方法走从库 -->
<bean id="DataBaseAdvice" class="com.aliaba.health.dao.dynamic.DataBaseAdvice">
<property name="methodKey">
<list>
<value>select</value>
<value>query</value>
<value>find</value>
<value>count</value>
</list>
</property>
<property name="showLog" value="false"/>
</bean> <!-- 切面配置 -->
<aop:config>
<!-- 配置切点:第一个*表示匹配所有方法的返回值类型,.表示当前包下所有类的方法,..表示当前包下及此包下所有自爆中的所有类方法;
第二个*表示所有类名,第三个*表示所有方法名,(..)表示所有方法参数-->
<aop:pointcut expression="execution(* com.alibaba.health.dao..*.*(..))" id="cutPoint"/>
<!-- 定义通知器 -->
<aop:advisor advice-ref="DataBaseAdvice" pointcut-ref="cutPoint"/>
</aop:config>
此时就完成了主从数据库读写分离的代码和xml配置,尤其可见各种技术组件,在于是否能灵活运用。
使用Adivisor配置增强处理,来实现数据库读写分离的更多相关文章
- yii2的数据库读写分离配置
简介 数据库读写分离是在网站遇到性能瓶颈的时候最先考虑优化的步骤,那么yii2是如何做数据库读写分离的呢?本节教程来给大家普及一下yii2的数据库读写分离配置. 两个服务器的数据同步是读写分离的前提条 ...
- 使用Adivisor配置增强处理
使用Adivisor配置增强处理 实现步骤: 1.通过MethodBeforeAdivice接口实现前置增强处理 public class ServiceBeforeAdvisor implement ...
- EF架构~通过EF6的DbCommand拦截器来实现数据库读写分离~终结~配置的优化和事务里读写的统一
回到目录 本讲是通过DbCommand拦截器来实现读写分离的最后一讲,对之前几篇文章做了一个优化,无论是程序可读性还是实用性上都有一个提升,在配置信息这块,去除了字符串方式的拼接,取而代之的是sect ...
- centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数据库读写分离 双主搭建 mysql.history 第二十九节课
centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数 ...
- Linux安装Mycat1.6.7.4并实现Mysql数据库读写分离简单配置
1. Mycat简介 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务.ACID.可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群 一 ...
- Spring aop应用之实现数据库读写分离
Spring加Mybatis实现MySQL数据库主从读写分离 ,实现的原理是配置了多套数据源,相应的sqlsessionfactory,transactionmanager和事务代理各配置了一套,如果 ...
- CYQ.Data V5 数据库读写分离功能介绍
前言 好多年没写关于此框架的新功能的介绍了,这些年一直在默默地更新,从Nuget上的记录就可以看出来: 这几天在看Java的一些东西,除了觉的Java和.NET的相似度实在太高之外,就是Java太原始 ...
- 161220、使用Spring AOP实现MySQL数据库读写分离案例分析
一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...
- [转]Spring数据库读写分离
数据库的读写分离简单的说是把对数据库的读和写操作分开对应不同的数据库服务器,这样能有效地减轻数据库压力,也能减轻io压力. 主(master)数据库提供写操作,从(slave)数据库提供读操作,其实在 ...
随机推荐
- Mongo常用查询语法
一.查询 find方法 db.collection_name.find(); 查询所有的结果: select * from users; db.users.find(); 指定返回那些列(键): se ...
- 【转载】C#将字符串中字母全部转换为大写或者小写
在C#的编程开发过程中,有时候判断字符串是否相等时,并不关注字母的大小写,此时在C#中可以使用ToUpper方法将字符串中所有的字母转换为大写,使用ToLower方法可以将字符串中所有字母转换为小写. ...
- TypeScript入门一:配置TS工作环境
配置手动编译TS文件工作环境 配置webpack自动化打包编译工作环境(后面补充) 一.TypeScript入门学习引言 进入主题之前,首先说明这个系列的博客是我刚刚接触TypeScript的学习笔记 ...
- php中的特殊标签
参考:https://www.freebuf.com/column/212586.html 今天看到这篇文章讲到了ctf中的一些关于php标签的小姿势,我虽然不打ctf,但是平常做php的代码审计也经 ...
- 【nodejs代理服务器四】代理服务器增加频繁访问的ip加入黑名单
问题 渗透者在扫站的时候会频繁请求,我们可以做一些策略来封堵这些频繁访问的ip,把ip加入黑名单. 策略 2秒之内访问次数超过100,加入黑名单. 实现思路 初次访问把访问Ip作为键,访问ip,时间, ...
- Python基础笔记一
1. 分片的步长,默认为值1,表示为 xx[s:t:v] ----从索引s到索引t,每隔v,取对应索引位置的值 xx = 'hello,world' #从索引0-10,共11个字符 xx[2:] #从 ...
- ECU 自动化生产测试系统
概述 ECU(Electronic Control Unit) 是现代车辆中最重要的部件之一,其稳定性.可靠性对车辆安全性的影响至关重要.如何保证ECU 生产质量和效率.如何在生产过程中对ECU 进行 ...
- async/await中reject的问题
promise 返回的 resolve 对象可能用 await 去接,但是 reject 无法用 await 接收到,所以要用 try catch 去处理 例如发送邮件的接口设置: async fun ...
- Selenium常用API的使用java语言之17-文件上传
对于通过input标签实现的上传功能,可以将其看作是一个输入框,即通过sendKeys()指定本地文件路径的方式实现文件上传. 创建upfile.html文件,代码如下: <html> & ...
- jquery点击显示或隐藏
点击第一个dd,给第一li添加class,点击第二个dd,给第二个li添加class,以此类推 $(function(){ $("dd > a").click(fun ...