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)");
}
}