Springboot AOP自定义注解方式和日志应用demo

1.引用依赖基于springboot

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

2. 注解说明

// 2.1 指定一个类为切面类
@Aspect

// 2.2 指定切入点表达式
@Pointcut("execution(*com.yarm.service.demo.insert(..))")
    //表示匹配所有方法,不建议使用
    2.2.1 execution(* *(..))

    //表示匹配com.yarm.service.demo.DemoService中所有的公有方法
    2.2.2 execution(public *com.yarm.service.demo.DemoService.*(..))

    //表示匹配com.yarm.service.demo包及其子包下的所有方法
    2.2.3 execution(*com.yarm.service.demo..*.*(..))


// 前置通知: 目标方法之前执行
@Before("pointCut_()")

// 后置通知:目标方法之后执行(始终执行)
@After("pointCut_()")

// 环绕通知:目标方法前后执行
@Around

// 返回后通知: 执行方法结束前执行(异常不执行)
@AfterReturning("pointCut_()")

// 异常通知:  出现异常时候执行
@AfterThrowing("pointCut_()")

3. 应用

3.1 DemoService类

package com.yarm.service.demo;

import com.yarm.pojo.http.ResponseApi;
import com.yarm.service.annotation.MyAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * Created with IDEA
 * author:Yarm.Yang
 * Date:2019/10/30
 * Time:18:04
 * Des:
 */
@Service
@Slf4j
public class DemoService {

    @MyAnnotation(name = "注解拦截")
    public ResponseApi<String> insert(Long id){
        this.getData();
        // 写入
        log.info("------注解拦截执行写入完成------");

        // 返回
        return new ResponseApi<>();
    }


    public ResponseApi<String> update(String name){
        this.getData();
        // 执行update
        log.info("------方法拦截执行update完成------");

        // 返回
        return new ResponseApi<>();
    }

    // 写入前拼接数据
    private void getData() {
        log.info("------执行业务逻辑------");
    }
}

3.2. 定义aop类

package com.yarm.service.aop;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;

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

/**
 * Created with IDEA
 * author:Yarm.Yang
 * Date:2019/10/30
 * Time:17:41
 * Des:
 */
@Aspect
@Component
@Slf4j
public class AopDemo {

    public static String LOG_AOP_PERFIX = "DemoTestSpringAop";

/*
整个表达式可以分为五个部分:

 1、execution(): 表达式主体。

 2、第一个*号:表示返回类型,*号表示所有的类型。

 3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。

 4、第二个*号:表示类名,*号表示所有的类。

 5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。
 @pointcut("execution(* com.sample.service.impl..*.*(..))")
*/

    // 以下注解方式
    // 注解方式定义切点
    @Pointcut("@annotation(com.yarm.service.annotation.MyAnnotation)")
    public void myAnnotationPointCut(){}

    // 以下是非注解方式
    // 这个com.yarm.service.demo包下的所有方法及方法参数
    @Pointcut("execution(* com.yarm.service.demo..*.*(..))")
    public void myPointCut(){}



    // 执行before
    @Before("myAnnotationPointCut()")
    public void myAnnotationBefore(){
        System.out.println(LOG_AOP_PERFIX + "执行before");
    }

    // 执行after
    @After("myAnnotationPointCut()")
    public void myAnnotationAfter(){
        System.out.println(LOG_AOP_PERFIX + "执行after");
    }

    // 执行Around
    @Around("myPointCut()")
    public void myAnnotationAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println(LOG_AOP_PERFIX + "执行Around前");


        Map<String, Object> reqParam = getReqParam(joinPoint);

        if (reqParam.size() > 0) {
            log.info("入参:{}",JSONObject.toJSONString(reqParam));
        }

        // 让目标方法执行
        Object proceedResult = joinPoint.proceed(joinPoint.getArgs());
        log.info("出参:{}",JSONObject.toJSONString(proceedResult));

        System.out.println(LOG_AOP_PERFIX + "执行Around后");
    }


    // 注解执行AfterThrowing
    @AfterThrowing("myPointCut()")
    public void myAnnotationAfterThrowing(){
        System.out.println(LOG_AOP_PERFIX + "执行afterThrowing");
    }

    private static Map<String, Object> getReqParam(ProceedingJoinPoint joinPoint) {
        // 参数值
        Object[] args = joinPoint.getArgs();
        ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String[] parameterNames = pnd.getParameterNames(method);

        Map<String, Object> paramMap = new HashMap<>(32);
        for (int i = 0; i < parameterNames.length; i++) {
            paramMap.put(parameterNames[i], args[i]);
        }
        return paramMap;
    }

}

4. 仓库地址:https://github.com/15902124763/share-demo-parent

git clone [email protected]:15902124763/share-demo-parent.git

发布了65 篇原创文章 · 获赞 38 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/HelloWorldYangSong/article/details/102842940