您的位置:首页 > 运维架构

基于schema的AOP,实现日志记录Demo

2014-08-14 17:08 507 查看
笔者今天使用<aop:aspect>配置文件的形式,外加注解,一个接口,一个日志记录类,实现访问某些指定Controller层方法时候记录日志的功能,并在注解中传入参数functionCode和menuCode,供日志记录类使用,

如下为Demo代码:

1.准备工作,一个注解的接口类

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/*
* 业务日志接口
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface SaveLog {

//接口成员:基本以及衍生的数据类型  无入参 无异常
String menuCode();
String functionCode();
}
说明:SaveLog接口必须使用@标注,可解释为标签;接口的参数成员menuCode,functionCode必须是无参的,且是八种基本数据类型及其衍生类;如List menu(),就是错误的。

2.Controller里的调用方法

/**
*
*
* 〈日志记录Demo入口〉
*
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@ResponseBody
@RequestMapping("/aopTest.action")
@SaveLog(menuCode="10",functionCode="20")
public Map<String, Object> aopTest(String a){
Map<String, Object> map = new HashMap<String, Object>();
map.put("aopTest", "true");
return map;
}


说明:这里请重点关注@SaveLog,并且传入参数menuCode="10"和functionCode="20",aopTest(String a)方法传入参数String a,返回一个Map对象,这些参数打算在日志记录里捕获。

3.Spring里的配置文件



<!--  logSave切面配置 -->
<aop:config proxy-target-class="true">
<aop:aspect ref="SaveLog">
<aop:pointcut expression="execution(* com.suning.sample.web.*.*(..))"
id="SaveLogPoint"/>
<aop:after-returning method="saveBusinessLog"
pointcut-ref="SaveLogPoint"  returning="res"/>
</aop:aspect>
</aop:config>
<bean id="SaveLog" class="com.suning.schema.aop.SaveLogImpl"></bean>


说明:proxy-target-class="true"是指使用CGLIB的动态代理,定义一个切面SaveLog指的是SaveLogImpl这个类,切点是com.suning.sample.web包下所有类的所有方法,第一个*是指返回值任意,第二个*指com.suning.sample.web包下任意类,第三个*指任意方法,(..)指方法参数任意;在切入点上的方法执行结束后(after-return),调用切面SaveLog的saveBusinessLog()方法,并传入参数res:

4.重点:此处为实现记录业务日志的关键类SaveLogImpl.java

package com.suning.schema.aop;

import java.lang.reflect.Method;
import java.util.Map;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

/*
* 切面增强实现类
*/
public class SaveLogImpl{

public void saveBusinessLog(JoinPoint joinPoint, Map<String,Object> res){
// 得到类路径
String classType = joinPoint.getTarget().getClass().getName();
// 得到方法名
String methodName = joinPoint.getSignature().getName();
MethodSignature jp = (MethodSignature) joinPoint.getSignature();
Method method = jp.getMethod();
Class<?>[] parameterTypes = method.getParameterTypes();
Class<?> className = null;
try {
className = Class.forName(classType);
method = className.getMethod(methodName, parameterTypes);
}catch(Exception e){
System.out.println("抛异常");
}
SaveLog desc = method.getAnnotation(SaveLog.class);
System.out.println("SaveLog注解参数functionCode:" + desc.functionCode());
System.out.println("SaveLog注解参数menuCode:" + desc.menuCode());
}
}


说明:我的demo里重点是展现获取连接点相关的参数,包括如下三个参数



还记得配置文件中这个么?



其实他是aopTest作为参数传给了saveBusinessLog这个记录日志的业务方法,如下:



5:测试,地址栏中输入如下地址,地址中传入参数a=1



查看saveBusinessLog()方法是否获取了连接点的相关值:



心得:同一pointCut下的增强方法均会执行,小技巧就是在配置文件中最好细化切入点。不赘述。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐