SpringBoot+AOP+自定义注解

Posted zhouyon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot+AOP+自定义注解相关的知识,希望对你有一定的参考价值。

  为了记录日志的使用常常需要写大量而又重复的代码,而通过注解的形式可以大量的减少代码量;

  

一.maven引入AOP的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

二.自定义注解

package com.zhou.blog.business.annotation;

import com.zhou.blog.business.enums.PlatformEnum;

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

/**
 * 日志记录、自定义注解
 **/
//定义是用在方法上
@Target({ElementType.METHOD})
// 定义是在运行时生效
@Retention(RetentionPolicy.RUNTIME)
public @interface BussinessLog {
    /**
     * 业务的名称
     */
    String value() default "";

    /**
     * 平台,默认为后台管理
     */
    PlatformEnum platform() default PlatformEnum.ADMIN;

    /**
     * 是否将当前日志记录到数据库中
     */
    boolean save() default true;
}

三.定义切面

package com.zhou.blog.business.aspect;

import com.zhou.blog.business.annotation.BussinessLog;
import com.zhou.blog.business.enums.PlatformEnum;
import com.zhou.blog.business.service.SysLogService;
import com.zhou.blog.util.AspectUtil;
import com.zhou.blog.util.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * AOP切面记录日志
 **/
@Slf4j
@Aspect
@Component
public class BussinessLogAspect {
    @Autowired
    private SysLogService logService;


    @Pointcut(value = "@annotation(com.zhou.blog.business.annotation.BussinessLog)")
    /*
     *   @Pointcut语法详解
     *  https://blog.csdn.net/qq_26860451/article/details/100554377
    */
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object writeLog(ProceedingJoinPoint point) throws Throwable {
        //环绕通知=前置+目标方法执行+后置通知,proceed方法就是用专于启动目标方法执行的。
        //先执行业务
        Object result = point.proceed();

        try {
            //handle(point);
            /*
            *
            *执行的内容
            * 
            */
        } catch (Exception e) {
            log.error("日志记录出错!", e);
        }

        return result;
    }

    private void handle(ProceedingJoinPoint point) throws Exception {
        Method currentMethod = AspectUtil.INSTANCE.getMethod(point);
        //获取操作名称
        BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class);
        boolean save = annotation.save();
        PlatformEnum platform = annotation.platform();
        String bussinessName = AspectUtil.INSTANCE.parseParams(point.getArgs(), annotation.value());
        String ua = RequestUtil.getUa();

        log.info("{} | {} - {} {} - {}", bussinessName, RequestUtil.getIp(), RequestUtil.getMethod(), RequestUtil.getRequestUrl(), ua);
        if (!save) {
            return;
        }

        logService.asyncSaveSystemLog(platform, bussinessName);
    }


}

 

四.使用注解的方法

package com.zhou.blog.controller;

import com.zhou.blog.business.annotation.BussinessLog;
import com.zhou.blog.business.entity.User;
import com.zhou.blog.business.service.SysUserService;
import com.zhou.blog.framework.object.ResponseVO;
import com.zhou.blog.util.PasswordUtil;
import com.zhou.blog.util.ResultUtil;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author ZHOU
 * @date 2020/5/3 23:14
 */
@RestController
@RequestMapping("/user")
public class RestUserController {
    @Autowired
    private SysUserService userService;
    
    @PostMapping(value = "/add")
  //使用自定义注解 @BussinessLog(
"添加用户") public ResponseVO add(User user) { User u = userService.getByUserName(user.getUsername()); if (u != null) { return ResultUtil.error("该用户名["+user.getUsername()+"]已存在!请更改用户名"); } try { user.setPassword(PasswordUtil.encrypt(user.getPassword(), user.getUsername())); userService.insert(user); return ResultUtil.success("成功"); } catch (Exception e) { e.printStackTrace(); return ResultUtil.error("error"); } } }

技术图片

 

以上是关于SpringBoot+AOP+自定义注解的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot利用自定义注解实现AOP

springboot 切换数据源(自定义注解,Aop)

springboot 切换数据源(自定义注解,Aop)

Springboot+自定义注解+自定义AOP前置增强+自定义异常+自定义异常捕获

SpringBoot 中的 Aop + 自定义注解

SpringBoot 中的 Aop + 自定义注解