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 git@github.com:15902124763/share-demo-parent.git