SpringAOP之日志管理
来源:互联网 发布:java快速开发平台比较 编辑:程序博客网 时间:2024/05/18 01:58
所谓AOP就是面向切面编程,简单的说就是在原来的方法基础上通过AOP切面对该方法进行增强。
一、Spring默认不支持@AspectJ风格的切面声明,为了支持需要在配置文件中添加如下配置:
<aop:aspectj-autoproxy/>
如下所示:
注:以上配置如果在controller层和service层中都用到,那么都需要在controller的配置和spring主配置都添加,如果不添加的效果在下面会有讲解。
二、定义切面aspect
1、定义切入面:在所定义的类中使用注解@Aspect即表示该类作为切面,如:
2、定义切入点:在这里我使用的是注解的方式(也可以使用较常用的通配符方式)
2.1 定义注解:
3、定义通知:根据业务需求自己定义,在这里我使用的是后置通知:即表示的是在使用该注解@LogController方法执行完之后再执行此切面方法
getControllerMethodDescription()
/** * 获取注解中对方法的描述信息 用于Controller层注解 * * @param joinPoint 切入点 * @return 方法描述 * @throws Exception */ @SuppressWarnings("rawtypes") private Map<String, String> getControllerMethodDescription(JoinPoint joinPoint) throws Exception { Map<String, String> result = new HashMap<String, String>(); //类名 String targetName = joinPoint.getTarget().getClass().getName(); //方法名称 String methodName = joinPoint.getSignature().getName(); //获取入参列表 Object[] arguments = joinPoint.getArgs(); //类对象 Class<?> targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { //获取注解对象 LogController logController=method.getAnnotation(LogController.class); result.put("logType", logController.logType().toString()); result.put("operation", logController.operation()); result.put("description", targetName+joinPointStr+methodName+leftJoinStr+getParamsRemark(joinPoint,logController, arguments)+rightJoinStr); break; } } } return result; }
getParamsRemark()
private String getParamsRemark(JoinPoint joinPoint,LogController logController, Object[] param){ System.out.println(logController.propertys() +"=========="); //如果没传递参数属性,说明传递的是对象 if(StringUtils.isBlank(logController.propertys())){ return getMethodParams(joinPoint); } if(param ==null || param.length==0){ param[0]=""; } //获取参数属性 name,age String propertys = logController.propertys(); StringBuffer sb = new StringBuffer(); if(propertys == null || "".equals(propertys)){ return sb.toString(); } //分割获取参数属性名称 name age String[] propertysRemark = propertys.split(splitParaStr); if(propertysRemark == null || propertysRemark.length == 0){ return sb.toString(); } int count = 0; for (int i=0;i<propertysRemark.length;i++) { Object name=null; if(param[0] instanceof String){ //表明是多个参数,否则就是对象 name=param[i]; }else{ name=param[0]; } //参数属性对应的值 String value = propertysRemark[i]; if(count == propertysRemark.length){ sb.append(propertysRemark[i] + splitNameValueStr + getID(name, value) +splitParaStr); }else{ sb.append(propertysRemark[i] + splitNameValueStr + getID(name, value)); } count++; sb.append(splitParaStr); } return sb.substring(0, sb.length()-1).toString(); }
getID()
/** * 通过java反射来从传入的参数object里取出我们需要记录的id,name等属性, * 此处我取出的是id */ private String getID(Object obj,String param){ if(obj instanceof String){ return obj.toString(); } if(obj instanceof Integer){ return obj.toString(); } //构造set和get PropertyDescriptor pd = null; Method method = null; String v = ""; try{ pd = new PropertyDescriptor(param,obj.getClass()); method = pd.getReadMethod(); v = String.valueOf(method.invoke(obj)); }catch (Exception e) { e.printStackTrace(); } return v; }
getMethodParams()
/** * * @描述:获取方法参数 * @创建人:rz.li * @创建时间:2017年7月18日上午9:36:04 * @param joinPoint * @return */ private String getMethodParams(JoinPoint joinPoint) { String params = ""; if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) { for (int i = 0; i < joinPoint.getArgs().length; i++) { Object object = joinPoint.getArgs()[i]; try { params += JSONUtils.obj2json(object) + ";"; } catch (Exception e) { e.printStackTrace(); } } } return params; }
4、开始使用切面:
在Controller层中
5、测试结果:
三、异常信息的处理
1、定义:对于异常信息的AOP,跟上面定义的方式一样,同样使用注解方式,代码如下:
@Pointcut("@annotation(com.demo.annotation.LogService)") public void serviceAspect() {}
2、注解:
@Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LogService { /** 要执行的操作类型比如:add操作 **/ public LogTypeEnum logType() default LogTypeEnum.SYS_LOG; /** 要执行的具体操作比如:添加用户 **/ public String description() default "";}
3、使用:
使用后置异常通知进行对Service层异常信息的捕获,此时在service方法中不需要try-catch捕获异常信息,如下所示:
@LogService(logType=LogTypeEnum.SYS_LOG,description="测试aop异常捕获") @Override public void testAop(BatchSellPO b) { int i=1/0; System.out.println(i); }
具体异常处理逻辑
@AfterThrowing(pointcut = "serviceAspect()", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Throwable e) { try { //TODO 获取用户的信息 String userId="123"; System.out.println("=====异常通知开始====="); System.out.println("异常代码:" + e.getClass().getName()); System.out.println("异常信息:" + e.getMessage()); System.out.println("异常方法:" + joinPoint.getTarget().getClass().getName()+joinPointStr+joinPoint.getSignature().getName() + "()"); System.out.println("方法描述:" + getServiceMethodDescription(joinPoint)); System.out.println("请求人ID:" + userId); System.out.println("请求IP:" + request.getRemoteAddr()); System.out.println("请求参数:" + getMethodParams(joinPoint)); /*==========数据库日志=========*/ SysLog log = new SysLog(); //保存数据库 //sysLogService.insert(log); System.out.println("=====异常通知结束====="); } catch (Exception e2) { logger.error(e2.getMessage(), e2); } }
getServiceMethodDescription()
/** * @描述:获取注解中对方法的描述信息 用于Service层注解 * @创建人:rz.li * @创建时间:2017年8月31日上午10:26:16 * @param joinPoint * @return 方法描述 * @throws Exception */ @SuppressWarnings("rawtypes") private Map<String, Object> getServiceMethodDescription(JoinPoint joinPoint) throws Exception { Map<String, Object> result = new HashMap<String, Object>(); String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class<?> targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { result.put("logType", method.getAnnotation(LogService.class).logType()); result.put("description", method.getAnnotation(LogService.class).description()); break; } } } return result; }
4、测试
在访问的时候没进入代理方法,看异常信息发现默认使用的是jdk代理(接口代理),而AOP切面的注解时基于类的代理,故改为cglib代理(类代理),由此可判断在spring主配置文件中没有添加
<aop:aspectj-autoproxy proxy-target-class="true"/>
添加配置之后测试结果如下:
说明异常切面已成功!
阅读全文
0 0
- SpringAOP之日志管理
- springAop日志管理
- SpringAop进行日志管理。
- SpringAop日志管理
- 基于springAop的日志管理功能
- SpringAOP +log4J+注解的 日志管理
- SpringAop拦截controller进行日志管理
- springAop之 记录登入日志
- springAOP面向切面编程之日志记录功能
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)里面的坑之 同一个controller部分方法可以拦截,部分方法拦截不了
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- CSU 1505 酷酷的单词 (简单题)
- 简单loading
- spring boot 学习笔录(一)
- java中关键词final和static的使用
- Pycharm去除波浪线
- SpringAOP之日志管理
- [Azure]使用Powershell获取ASM和ARM存储的实际使用量
- linux 安装rar 右键直接解压
- 《Windows程序设计》读书笔二十三 尝试互联网
- android填充内存工具(辅助测试)
- css-6.文本格式化
- 求两个圆交叉区域面积
- 目标跟踪算法
- MySql高级—视图、函数、存储过程、触发器