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