Spring AOP自定义Annotation(注解)记录日志

   什么是AOP?

    它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。如果说面向对象编程(oop)是水平扩展的话,那么aop则是纵向的扩展,使程序立体化。

   定义一个注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Loggable {
    /** 操作类型(INSERT、UPDATE、SELECT、DELETE)*/
    public String optType();
    /** 描述 */
    public String describe();
    /** 模块 */
    public String module();

   自定义注解

@Retention:标示注解在什么时候可见(运行时可见、仅在.class文件及源代码中可见、仅在源代码中可见),value可用参数有:
  RetentionPolicy.RUNTIME    标示该注解可以再运行时通过反射找到(ORM框架许多注解使用了该参数)
  RetentionPolicy.CLASS    标示该注解保存在.class文件中,但在运行时不能通过反射找到
  RetentionPolicy.SOURSE    标示该注解只在源码中可见

@Target:标示该注解用于注解什么元素(类、方法、变量等),value可用参数有:
  ElementType.PACKAGE    标示该注解用于注解包声明
  ElementType.ANNOTATION_TYPE    标示该注解用于注解其他注解
  ElementType.CONSTRUCTOR    标示该注解用于注解构造函数
  ElementType.FIELD    标示该注解用于注解成员变量
  ElementType.METHOD    标示该注解用于注解方法
  ElementType.TYPE    标示该注解用于注解类,接口,枚举类型
  ElementType.PARAMETER    标示该注解用于注解参数
  ElementType.LOCAL_VARIABLE    标示该注解用于注解局部变量

   定义一个切面类(根据项目情况在里面科将日志记录存到数据库):

@Aspect
@Component(value = "loggerAspect")
public class LoggerAspect {
    private Logger logger = LoggerFactory.getLogger(LoggerAspect.class);
    //切入点:* com.wb.wbao.web.*.*(..)路径下和使用了@Loggable注解的方法
    @Pointcut("execution(public * com.wb.wbao.web.*.*(..)) && @annotation(com.wb.wbao.common.annotation.Loggable)")
    public void log(){
    }
    @AfterReturning(value = "log()", returning = "retVal")
    public void log(JoinPoint joinPoint, Object retVal) {
        // 获取参数
        Object[] params = joinPoint.getArgs();
        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        Class<?> targetClass = joinPoint.getTarget().getClass();
        Method method = null;
        for (Method mt : targetClass.getMethods()) {
            if (methodName.equals(mt.getName())) {
                method = mt;
                break;
            }
        }
        Loggable loggable = method.getAnnotation(Loggable.class);
        if(Objects.isNull(loggable)){
            return;
        }
        logger.info("loggable desc:{}, optType:{}, module:{},params:{}", loggable.describe(), loggable.optType(), loggable.module(), params);
        //loggable desc:登录, optType:POST, module:LOGIN,params:[User{loginName='wangbao', password='wangbao'}
    }
 
    @AfterThrowing(value = "log()", throwing = "ex")
    public void log(JoinPoint joinPoint, Throwable ex) {
        // 获取参数
        Object[] params = joinPoint.getArgs();
        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        Class<?> targetClass = joinPoint.getTarget().getClass();
        Method method = null;
        for (Method mt : targetClass.getMethods()) {
            if (methodName.equals(mt.getName())) {
                method = mt;
                break;
            }
        }
        Loggable loggable = method.getAnnotation(Loggable.class);
        if(Objects.isNull(loggable)){
            return;
        }
        logger.info("loggable desc:{}, optType:{}, module:{}, exception:{}, params:{}", loggable.describe(), loggable.optType(), loggable.module(), ex.getMessage(),  params);
        //loggable desc:登录, optType:POST, module:LOGIN, exception:/ by zero, params:[User{loginName='wangbao', password='wangbao'}
    }
}

   实际使用方法:

@Loggable(describe = "登录", optType = "POST", module = "LOGIN")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
     public CommonDTO login(@RequestBody User user) {...}

转载于:https://my.oschina.net/u/3734816/blog/3026191

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值