第一步:添加aop相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
第二步:写自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyAnnotation {
String value() default "";
String name() default "";
}
如上代码所示,该注解有两个属性,value和name
第三步:写切面逻辑
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class AopAdvice {
// 1.先写切点,对应注解(nomal.aop.MyAnnotation是自定义注解的位置)
@Pointcut("@annotation(nomal.aop.MyAnnotation)")
public void myPointcut(){}
// 2.写切面的业务逻辑,myPointcut()是1中的方法名
@Around("myPointcut()")
public Object doAop(ProceedingJoinPoint joinPoint) throws Throwable {
// 如果业务逻辑要用到注解上的属性值
MyAnnotation annotation=getObject(joinPoint);
// 写切面 前面的页面逻辑
// 原本的业务
Object result = joinPoint.proceed();
// 写切面 后面的页面逻辑
return result;
}
/**
* 获取对应 注解的对象
* @param joinPoint 切入点
* @return 注解的对象
* @throws Exception 异常
*/
MyAnnotation getObject(ProceedingJoinPoint joinPoint) throws Exception {
//1.1获取目标对象对应的字节码对象
Class<?> targetCls=joinPoint.getTarget().getClass();
//1.2获取目标方法对象
//1.2.1 获取方法签名信息从而获取方法名和参数类型
Signature signature=joinPoint.getSignature();
//1.2.1.1将方法签名强转成MethodSignature类型,方便调用
MethodSignature ms= (MethodSignature)signature;
//1.2.2通过字节码对象以及方法签名获取目标方法对象
Method targetMethod=targetCls.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
//1.3获取目标方法对象上注解中的属性值
//1.2.3 获取方法上的自定义MyAnnotation 注解
MyAnnotation annotation=targetMethod.getAnnotation(MyAnnotation.class);
return annotation;
}
举个栗子
假设我的业务逻辑是要输出某个方法的执行时间,并输出注解中的value和name
那么编辑切面逻辑可以如下:
@Around("myPointcut()")
public Object doAop(ProceedingJoinPoint joinPoint) throws Throwable {
// 如果业务逻辑要用到注解上的属性值
MyAnnotation annotation=getObject(joinPoint);
// 切面 前面的页面逻辑
System.out.println("切面->记录开始时间");
long startTime = System.currentTimeMillis();
// 原本的业务
Object result = joinPoint.proceed();
// 切面 后面的页面逻辑
System.out.println("切面->记录结束时间");
long endTime = System.currentTimeMillis();
System.out.println("切面->本次业务用时:"+(endTime-startTime)+"ms");
System.out.println("切面->value:"+annotation.value());
System.out.println("切面->name:"+annotation.name());
return result;
}
然后找个业务的方法上加上注解
@MyAnnotation(name = "测试",value = "666")
public void doExecute() throws Exception{
System.out.println("业务逻辑开始");
TimeUnit.SECONDS.sleep(3);
System.out.println("业务逻辑结束");
}
当业务逻辑执行后,可以看到输出如下图所示