博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
aop切入mapper接口
阅读量:5363 次
发布时间:2019-06-15

本文共 7120 字,大约阅读时间需要 23 分钟。

***************************************分割线******************************************************

参考:

两位老哥的回复。

想着在service层再单独写个方法去调用mapper;

public int updateOrderStatus(Map param){        log.info("updateOrderStatus==============="+param+"======================");        return  rechargeMapper.updateOrderStatus(param);    }
int uptNum = this.updateOrderStatus(orderMap);

但是发现

所以重新包装一下mapper类,新建一个类

@Servicepublic class RechargeServiceAop {    private org.slf4j.Logger log = LoggerFactory.getLogger(String.valueOf(RechargeServiceAop.class));    @Autowired    private RechargeMapper rechargeMapper;    public int updateOrderStatus(Map param){        log.info("updateOrderStatus==============="+param+"======================");        return  rechargeMapper.updateOrderStatus(param);    }}

将业务层调用mapper的方法改为调用新的实现类

int uptNum = rechargeServiceAop.updateOrderStatus(orderMap);

然后去切这个新的类方法

@After("execution(public * com.zhx.recharge.service.RechargeServiceAop.updateOrderStatus(..))")

***************************************分割线******************************************************

之前引用的博客方法在junit本地测试可用,但是更新上服务器不可用。

***************************************分割线******************************************************

https://blog.csdn.net/weixin_35562755/article/details/78689862?utm_source=copy

以下为项目dao层的简单接口定义: 

public interface BaseDao {public List
> queryListData(String sql, Object[] o);public List
> queryListDataNoParams(String sql);public List queryList(String sql, Object[] o);public
List
queryObjList(String sql, Object[] args, Class
clazz);public int queryForInt(String sql, Object[] o);public int addOrUpdate(String sql, Object[] o);}

 

可以发现传参比较简单,基本都是传入sql,以及一些sql参数,我们只需要拦截到这些要执行的方法,通过JAVA反射拿到对应的参数,进行控制台输出就好了。但是仅仅输出了sql还不够,我们还需要显示的知道这个方法的调用过程。这里通过Java线程来获取方法运行栈的信息。对比看了下具有sql监控的淘宝数据源druid,其实现逻辑大体上也是运用了AOP的原理进行SQL的监控。

废话不少说直接上代码:

1)自定义一个方法拦截器 DisplayExecuteSqlInterceptor :

package com.XXX.CCC.aop;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.apache.commons.lang.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.lang.reflect.Method;/** * * 方法拦截  粒度在方法上 * * @desc 调试管理 利用 AOP 原理, 在开发模式下于控制台展示 dao层 的实际执行的SQL * 粘出来即可 在pl/sql下执行,已经替换掉 ? 了 * * @author luotianyi * @create 2017-11-30 14:03 **/public class DisplayExecuteSqlInterceptor implements MethodInterceptor {    private static final Logger log = LoggerFactory.getLogger(DisplayExecuteSqlInterceptor.class);    private static final String CONTROLLER ="CONTROLLER";    private static final String SERVICE ="SERVICE";    private static final String DAO ="DAO";    private static final String IMPL ="IMPL";    @Override    public Object invoke(MethodInvocation mi) throws Throwable {        //系统的开发模式        String codeModel =System.getProperty("codeModel");        String flag="true";        if(StringUtils.equals(flag,codeModel)){            //获取该方法的传参            Object[] ars = mi.getArguments();            //通过反射机制 获取到该方法 (Method 包含 作用域 返回类型  方法名  参数类型)            Method method= mi.getMethod();            //获取代理的对象 (也就是这个方法所在内存中的对象)            Object obj = mi.getThis();            Object [] params =new Object[]{} ;            String sql ="";            for(Object o :ars){                if(o instanceof Object[]){                    params= (Object[]) o;                }else if(o instanceof String){                    sql=(String) o;                }            }            Thread current = Thread.currentThread();            StackTraceElement[] elements =current.getStackTrace();            //倒序输出 栈帧 信息 ,过滤出 项目的代码 这里只过滤出(Controller / service impl / dao impl)层的代码,如需要其他的可自行遍历            if(elements !=null && elements.length>0){                //获得项目名                String packageName =DisplayExecuteSqlInterceptor.class.getPackage().getName();                packageName=StringUtils.substringBefore(packageName,".");                StringBuilder sb =new StringBuilder();                sb.append(" -------->本次执行SQL的代码在<--------- ");                sb.append('\n');                for(int i=elements.length ;i>0 ;i--){                    StackTraceElement e =elements[i-1];                    if(StringUtils.contains(e.getClassName(),packageName)){                        String cn=StringUtils.upperCase(e.getClassName());                        if(StringUtils.contains(cn,CONTROLLER)){                            sb.append( CONTROLLER+" 层 ->类名:"+e.getClassName()+",方法名:"+e.getMethodName()+",代码行数:"+e.getLineNumber()+"");                            sb.append('\n');                        }else if(StringUtils.contains(cn,SERVICE) &&StringUtils.contains(cn,IMPL) && e.getLineNumber()>0) {                            sb.append( SERVICE+" 层 ->类名:"+e.getClassName()+",方法名:"+e.getMethodName()+",代码行数:"+e.getLineNumber()+"");                            sb.append('\n');                        }else if(StringUtils.contains(cn,DAO) &&StringUtils.contains(cn,IMPL) && e.getLineNumber()>0 ){                            sb.append(DAO +" 层->类名:"+e.getClassName()+",方法名:"+e.getMethodName()+",代码行数:"+e.getLineNumber()+"");                            sb.append('\n');                        }                    }                }                log.info(sb.toString());            }            getExecuteSql(sql,params);        }        //执行被拦截的方法,切记,如果此方法不调用,则被拦截的方法不会被执行。        return mi.proceed();    }    private String getExecuteSql(String sql, Object[] params) {        if (StringUtils.isNotBlank(sql)) {            if (params != null && params.length > 0) {                int a = getCount(sql, '?');                int b = params.length;                if (a == b) {                    sql = StringUtils.replace(sql, "?", "XXXX");                    for (int i = 0; i < params.length; i++) {                        Object obj = params[i];                        if (StringUtils.isNotBlank(String.valueOf(obj)) && StringUtils.isNumeric(String.valueOf(obj))) {                            obj = Integer.valueOf(String.valueOf(obj));                        } else {                            obj = "'" + obj + "'";                        }                        sql = sql.replaceFirst("XXXX", String.valueOf(obj));                    }                } else {                    log.info("参数个数传的不正确, sql中 需要 :{} 个参数,实际传入参数为 :{} 个。", a, b);                    return null;                }            }        }        StringBuilder sb =new StringBuilder();        sb.append(" ----------->本次执行sql为:<----------- ");        sb.append('\n');        sb.append(sql+'\n');        log.info(sb.toString());        return sql;    }    private  int getCount(String sql ,char a ){        int count=0;        if(StringUtils.isNotBlank(sql)){            for (int i = 0; i < sql.length(); i++) {                if(sql.charAt(i)==a){                    count++;                }            }        }        return count;    }}

 

2)在spring配置文件中,添加下一下的配置:

转载于:https://www.cnblogs.com/SimonHu1993/p/9772476.html

你可能感兴趣的文章
【题解】luogu p2340 奶牛会展
查看>>
解决响应式布局下兼容性的问题
查看>>
使用DBCP连接池对连接进行管理
查看>>
【洛谷】【堆+模拟】P2278 操作系统
查看>>
hdu3307 欧拉函数
查看>>
Spring Bean InitializingBean和DisposableBean实例
查看>>
[容斥][dp][快速幂] Jzoj P5862 孤独
查看>>
软件开发工作模型
查看>>
Java基础之字符串匹配大全
查看>>
面向对象
查看>>
lintcode83- Single Number II- midium
查看>>
[工具] Sublime Text 使用指南
查看>>
Web服务器的原理
查看>>
#10015 灯泡(无向图连通性+二分)
查看>>
HAL层三类函数及其作用
查看>>
web@h,c小总结
查看>>
Data Structure 基本概念
查看>>
NEYC 2017 游记
查看>>
[搬运] 写给 C# 开发人员的函数式编程
查看>>
Python之旅Day14 JQuery部分
查看>>