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