pom中添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
常规切面使用
切入指定包类目录,如
@Pointcut("execution(* sb.simple.aspectj.normal.*.*(..))")
@Pointcut参数正则可以自行了解一下
-
切面类
package sb.simple.aspectj.normal; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.context.annotation.Configuration; import java.util.Arrays; /** * AspectJ * 五种通知注解:@Before/@Around/@After/@AfterReturning/@AfterThrowing */ @Configuration @Aspect public class AJNormal { @Pointcut("execution(* sb.simple.aspectj.normal.*.*(..))") public void point() { } /** * 前置通知 * 连接点之前执行 */ @Before("point()") public void before(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("before() methodName:" + methodName + ", args:" + Arrays.toString(args)); } @Around("point()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("around() before proceed"); Object proceed = joinPoint.proceed(); System.out.println("around() after proceed methodName:" + methodName + ", args:" + Arrays.toString(args) + ", result:" + proceed); return proceed; } /** * 后置通知 * 连接点方法完成后执行 * 无论连接点执行成功与否该通知都会执行 */ @After("point()") public void after(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("after() methodName:" + methodName + ", args:" + Arrays.toString(args)); } /** * 连接点方法执行成功后执行 * 可以拿到返回结果 */ @AfterReturning(value = "point()", returning = "result") public void result(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("AfterReturning() methodName:" + methodName + ", args:" + Arrays.toString(args) + ", result:" + result); } /** * 连接点方法执行异常后执行 * 可以拿到异常信息 */ @AfterThrowing(value = "point()", throwing = "exception") public void afterThrowing(JoinPoint joinPoint, Exception exception) { String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println("afterThrowing() methodName:" + methodName + ", args:" + Arrays.toString(args) + ", exception:" + exception); } }
-
被切类
package sb.simple.aspectj.normal; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @Service @Component public class CalcService { public int add(int a, int b) { int result = a + b; System.out.println("CalcService->add() result:" + result); return a + b; } //测试AfterThrowing通知 public int divider(int a, int b) { int result = a / b; System.out.println("CalcService->divider() result:" + result); return result; } }
-
测试类
package sb.simple.aspectj; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import sb.simple.aspectj.annotation.CalcAnClass; import sb.simple.aspectj.annotation.CalcAnMethod; import sb.simple.aspectj.normal.CalcService; @SpringBootTest public class AJTest { /**普通切入*/ @Autowired private CalcService calcService; /* around() before proceed before() methodName:add, args:[1, 2] CalcService->add() result:3 AfterReturning() methodName:add, args:[1, 2], result:3 after() methodName:add, args:[1, 2] around() after proceed methodName:add, args:[1, 2], result:3 */ @Test public void testAdd() { calcService.add(1, 2); } /* around() before proceed before() methodName:divider, args:[3, 0] afterThrowing() methodName:divider, args:[3, 0], exception:java.lang.ArithmeticException: / by zero after() methodName:divider, args:[3, 0] */ @Test public void testDivider() { calcService.divider(3, 0); } /*不用@Service注解实例化aspectj就没用 CalcService->add() result:8 */ @Test public void testAddNew() { new CalcService().add(3, 5); } }
配合自定义注解使用
-
自定义注解
package sb.simple.aspectj.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) //METHOD->注解于方法 | TYPE->注解于类 @Target({ElementType.METHOD, ElementType.TYPE}) public @interface Require { String value(); }
-
被切类
package sb.simple.aspectj.annotation; import org.springframework.stereotype.Service; //注解于类 @Service @Require("in class") public class CalcAnClass { public void hi(String name) { System.out.println(getClass().getSimpleName() + ": hi:" + name); } }
package sb.simple.aspectj.annotation; import org.springframework.stereotype.Service; //注解于方法 @Service public class CalcAnMethod { @Require("in method") public void hi(String name) { System.out.println(getClass().getSimpleName() + ": hi:" + name); } }
-
切面类
在通知方法@Around中,通过ProceedingJoinPoint实例可以获取被切方法的方法名,方法参数,所在类,注解,注解参数等,可以通过这些数据对方法进行增强
package sb.simple.aspectj.annotation; 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.aspectj.lang.reflect.MethodSignature; import org.springframework.context.annotation.Configuration; import java.lang.reflect.Method; import java.util.Arrays; @Configuration @Aspect public class AJAnnotation { /**注解于类@within*/ @Pointcut("@within(sb.simple.aspectj.annotation.Require)&&execution(public * *.*(..))") public void pointClass() { } @Around("pointClass()") public Object aroundClass(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("aroundClass() in"); //获取在类上的注解中的属性值 String className = joinPoint.getTarget().getClass().getName(); Class<?> clz = Class.forName(className); Require require = clz.getAnnotation(Require.class); System.out.println("annotation(class), clzName:" + clz.getSimpleName()); String value = require.value(); System.out.println("annotation(class)->Require->value:" + value); return joinPoint.proceed(); } /**注解于方法@annotation*/ @Pointcut("@annotation(sb.simple.aspectj.annotation.Require)") public void point() { } @Around("point()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("aroundMethod() in"); //获取在方法上的注解的属性值 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Class<?> clz = joinPoint.getTarget().getClass(); String name = signature.getName(); Class[] parameterTypes = signature.getParameterTypes(); Method method = clz.getMethod(name, parameterTypes); System.out.println("annotation(method), clzName:" + clz.getSimpleName() + ", name:" + name + ", parameterTypes:" + Arrays.toString(parameterTypes)); Require require = method.getAnnotation(Require.class); String value = require.value(); System.out.println("annotation(method)->Require->value:" + value); return joinPoint.proceed(); } }
-
测试类
package sb.simple.aspectj; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import sb.simple.aspectj.annotation.CalcAnClass; import sb.simple.aspectj.annotation.CalcAnMethod; import sb.simple.aspectj.normal.CalcService; @SpringBootTest public class AJTest { /**配合自定义注解切入*/ @Autowired CalcAnClass calcAnClass; @Test public void anClass() { calcAnClass.hi("akali(class)"); } @Autowired CalcAnMethod calcAnMethod; @Test public void anMethod() { calcAnMethod.hi("annie(method)"); } }