最近帮同事实现一个对接口应用添加日志的功能,第一思路就是用SPRING AOP或写个代理类实现

以下用SPring aop实现

<!-- 切面通知实现类 -->
	<bean id="aspect" class="com.test.aop.logsystem.aop.LogAspect" />
	<aop:config>
		<!-- 切入点配置:婚配表达式,可以多个start -->
		<aop:pointcut id="pointcut" expression="(execution(* com.test.aop.logsystem.service..*.say*(..))) 
		|| (execution(* com.test..*.send*(..)))" />
		<!-- 切入点配置:婚配表达式,可以多个end -->
		<!--切面配置start -->
		<aop:aspect ref="aspect">
			<aop:before pointcut-ref="pointcut" method="beforeAdvice" />
			<aop:after pointcut="execution(* com.test.test..*.*(..))" method="afterFinallyAdvice" />
			<aop:after-returning pointcut-ref="pointcut" method="afterReturningAdvice" />
			<aop:after-throwing pointcut-ref="pointcut" method="afterThrowingAdvice" />
			<aop:around pointcut-ref="pointcut" method="aroundAdvice" />
		</aop:aspect>
		<!--切面配置end -->
	</aop:config>



package com.test.aop.logsystem.aop;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/**
 * 切面支持类,这里我采用的是 基于Schema的AOP,
 * 也可以用注解方式:使用@AspectJ风格的切面声明,
 * 但是spring默认不支持注解方式,需要加入<aop:aspectj-autoproxy/>这样Spring就能发现@AspectJ风格的切面并且将切面应用到目标对象
 * 
 * 作用:记录被拦截方法的:1:前置日志,2.后置返回日志 3.执行异常日志,4.环绕通知日志
 * 
 * @author 4*****
 *
 */
public class LogAspect {
       //前置通知
    public void beforeAdvice(JoinPoint joinPoint) {
    	//记录目标方法执行前的日志
    	System.out.println("===========before advice");
        /*System.out.println("=="+joinPoint.toString());//连接点所在位置的相关信息  
        System.out.println("=="+joinPoint.toShortString());     //连接点所在位置的简短相关信息  
        System.out.println("=="+joinPoint.toLongString());     //连接点所在位置的全部相关信息  
        System.out.println("=="+joinPoint.getThis());         //返回AOP代理对象  
        System.out.println("=="+joinPoint.getTarget());       //返回目标对象  
        System.out.println("=="+joinPoint.getArgs());       //返回被通知方法参数列表  
        System.out.println("=="+joinPoint.getSignature());  //返回当前连接点签名  
        System.out.println("=="+joinPoint.getSourceLocation());//返回连接点方法所在类文件中的位置  
        System.out.println("=="+joinPoint.getKind());        //连接点类型  
        System.out.println("=="+joinPoint.getStaticPart()); //返回连接点静态部分  
*/        
      //判断参数    
        if(joinPoint.getArgs() == null){//没有参数    
            return;    
        }    
        //获取方法名    
        String methodName = joinPoint.getSignature().getName();    
        //获取操作内容(参数类型 + 参数值)    
        String opContent = optionContent(joinPoint.getArgs(), methodName); 
        System.out.println(opContent);
        /*************记录日志到文件或数据库表,此处省略。。。。 start****************/


        /*************记录日志到文件或数据库表,此处省略。。。。 end****************/

}
    //后置最终通知
    public void afterFinallyAdvice(JoinPoint jp) {

        System.out.println("===========after finally advice");
    }
   //后置返回通知
	public void afterReturningAdvice(JoinPoint jp){
		//记录目标方法执行完成日志
		System.out.println("===========after Returning Advice");
	}
	//后置异常通知 
	public void afterThrowingAdvice(JoinPoint jp){
		//记录异常日志
		System.out.println("===========after Throwing Advice");
	}

	//环绕通知
	//使用proceed()方法来执行目标方法:
	public void aroundAdvice(ProceedingJoinPoint jp){
			System.out.println("===========around Advice");
			try {
				Object obj = jp.proceed();	//执行目标方法
			} catch (Throwable e) {
				e.printStackTrace();
				/********回滚,添加报警信息到监控服务器等处理,此处省略。。。。。。。********/

				/********回滚,添加报警信息到监控服务器等处理,此处省略。。。。。。。********/
			}
	}

	/**
	 * 使用Java反射来获取被拦截方法的参数值, 
     * 将参数值拼接为操作内容
	 * @param args 参数值
	 * @param mName 方法名
	 * @return
	 */
	public String optionContent(Object[] args, String mName){
		if(args == null){
			return null;
		}
		StringBuffer rs = new StringBuffer();
		rs.append(mName);
		String className = null;
		int index = 1;
		//遍历参数对象 
		for(Object info : args){
			//获取对象类型
			className = info.getClass().getName();
			className = className.substring(className.lastIndexOf(".") + 1);
			rs.append("[参数"+index+",类型:" + className + ",值:");
			//如果是基本数据类型,List,Map则直接获取值
			if(info instanceof String
					|| info instanceof Integer
					|| info instanceof Double
					|| info instanceof Float
					|| info instanceof BigDecimal
					|| info instanceof List
					|| info instanceof Map){
				rs.append(info);
			}else {
				//如果是domain对象则获取对象所有特性的get()方法,或者规范domain重写toString(),统一用toString();
				Method[] methods = info.getClass().getDeclaredMethods();
				// 遍历方法,判断get方法 
				for(Method method : methods){
					String methodName = method.getName();
					if(methodName.indexOf("get") == -1){//不是get方法 
						continue;
					}
					Object rsValue = null;
					try{

						rsValue = method.invoke(info);
					}catch (Exception e) {
						continue;
					}
					rs.append("(" + methodName+ ":" + rsValue + ")");
				}
			}
			rs.append("]");
			index ++;
		}
		return rs.toString();
	}
}