Spring的AOP实现日志记录

记录,备忘……

使用实例:

package test.aop;

public class Test {

    /**
     *
     * 使用spring的aop切面实现日志记录
     *      1 aop开启springboot: spring.aop.auto=true
     *      2 日志注解
     *      3 切面类
     *
     *  注解使用实例
     */
    @SysLog(operationType = "新增",description = "新增用户")
    public void addSomeThing(){
        // doSomeThing……
    }
}

 

日志注解:

package test.aop;


import java.lang.annotation.*;

/**
 * 系统日志注解
 *
 */

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {

    /**
     * 要执行的操作类型比如:add操作
     **/
    String operationType() default "";

    /**
     * 要执行的具体操作比如:添加用户
     **/
    String description() default "";

}

 

切面类:

package test.aop;

import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 日志切点类
 * 通知:advice(前置,后置,环绕)
 *
 */
@Slf4j
@Aspect
//@Order(value=6) // 多个切面时,使用order注解来进行设置顺序,值越小优先级越高
@Component
public class SysLogAspect {
    /**
     * 切点:配置切点表达式
     *      execution(* test.*.*(..))代表test包下所有类的所有方法都会被代理
     */
    @Pointcut("@annotation(test.aop.SysLog)")
    public  void logAspect() {
    }

    /**
     * 返回通知:方法返回时调用
     */
    @AfterReturning(value = "logAspect() && @annotation(sysLog)")
    public void around(JoinPoint point, SysLog sysLog) {
        // request请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //拦截的类名,如某个serviceImpl
        Class clazz = point.getTarget().getClass();
        //拦截的方法
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        // 获取request请求参数
        Map<String, String> parameterMap = ServletUtil.getParamMap(request);

        // 业务处理:存储日志数据……

    }

    /**
     *  前置通知:目标方法执行前执行
     */
    @Before(value="logAspect()")
    public void before(JoinPoint joinPoint){
        System.out.println("目标方法名为:" + joinPoint.getSignature().getName());
        System.out.println("目标方法所属类的简单类名:" +        joinPoint.getSignature().getDeclaringType().getSimpleName());
        System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
        //获取传入目标方法的参数
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println("第" + (i+1) + "个参数为:" + args[i]);
        }
        System.out.println("被代理的对象:" + joinPoint.getTarget());
        System.out.println("代理对象自己:" + joinPoint.getThis());
        /*
            执行结果:
                目标方法名为:getMethod
                目标方法所属类的简单类名:TestController
                目标方法所属类的类名:test.aop.ClientController
                目标方法声明类型:public
                // 此处参数即赋值后的形参
                    第1个参数为:
                    第2个参数为:
                被代理的对象:test.aop.ClientController@30c3876b
                代理对象自己:test.aop.ClientController@30c3876b

         */
    }

    /**
     *  后置通知:目标方法执行后执行
     */
    @After(value="logAspect()")
    public void after(JoinPoint joinPoint){
    }
    /**
     *  异常通知:目标方法异常时执行
     */
    @AfterThrowing(value="logAspect()")
    public void exeException(JoinPoint joinPoint){
    }


    /**
     *   环绕通知:自定义方法的执行时机。
     *
     *   ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中,
     *          Object proceed() throws Throwable               //执行目标方法
     *          Object proceed(Object[] var1) throws Throwable  //传入的新的参数去执行目标方法
     *
     *      方法返回值必须返回,因为环绕通知相当于代理动作。此时方法返回值即视为目标方法返回值
     */
    @Around(value="logAspect()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        //
        System.out.println("方法执行前处理……");
        // 执行目标方法
        Object result = joinPoint.proeed();
        //
        System.out.println("方法执行后处理……");
        return result;
    }




}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值