要在 Spring 中声明 AspectJ 切面, 只需要在 IOC 容器中将切面声明为 Bean 实例. 当在 Spring IOC 容器中初始化 AspectJ 切面之后, Spring IOC 容器就会为那些与 AspectJ 切面相匹配的 Bean 创建代理。
在切面类中需要定义切面方法用于响应响应的目标方法,切面方法即为通知方法,通知方法需要用注解标识,AspectJ 支持 5 种类型的通知注解:
@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行 。
@AfterRunning: 返回通知, 在方法返回结果之后执行
@AfterThrowing: 异常通知, 在方法抛出异常之后
@Around: 环绕通知, 围绕着方法执行
下面分别举例5中通知方法的使用
首先建立一个目标接口ArithmeticCalculator:
package lzj.com.spring.aop;
public interface ArithmeticCalculator {
int add(int i, int j);
int div(int i, int j);
}
然后创建接口的实现类ArithmeticCalculatorIml :
package lzj.com.spring.aop;
import org.springframework.stereotype.Component;
@Component("arithmeticCalculator")
public class ArithmeticCalculatorIml implements ArithmeticCalculator {
@Override
public int add(int i, int j) {
int result = i + j;
System.out.println("add->result:" + result);
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
System.out.println("div->result:" + result);
return result;
}
}
创建测试类:
package lzj.com.spring.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-aop.xml");
ArithmeticCalculator arithmetic = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator");
arithmetic.add(3, 2);
arithmetic.div(4, 2);
}
}
运行结果:
add->result:5 div->result:2
一、@Before前置通知
用@Before标识的方法为前置方法,在目标方法的执行之前执行,即在连接点之前进行执行。
示例如下:
package lzj.com.spring.aop;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogProxy {
@Before("execution(public int lzj.com.spring.aop.ArithmeticCalculator.*(int, int))")
public void beforMethod(JoinPoint point){
String methodName = point.getSignature().getName();
List
执行测试类,输出结果如下:
调用前连接点方法为:add,参数为:[3, 2] add->result:5 调用前连接点方法为:div,参数为:[4, 2] div->result:2
在目标方法add和div之前分别执行了前置通知方法。
二、@After后置通知方法
后置方法在连接点方法完成之后执行,无论连接点方法执行成功还是出现异常,都将执行后置方法。
三、@AfterRunning返回通知方法
当连接点方法成功执行后,返回通知方法才会执行,如果连接点方法出现异常,则返回通知方法不执行。返回通知方法在目标方法执行成功后才会执行,所以,返回通知方法可以拿到目标方法(连接点方法)执行后的结果
四、@AfterThrowing异常通知
异常通知方法只在连接点方法出现异常后才会执行,否则不执行。在异常通知方法中可以获取连接点方法出现的异常
五、@Around环绕通知
环绕通知方法可以包含上面四种通知方法,环绕通知的功能最全面。环绕通知需要携带 ProceedingJoinPoint 类型的参数,且环绕通知必须有返回值, 返回值即为目标方法的返回值。在切面类中创建环绕通知方法
六,@Pointcut切入点设置设置以上注释方法的使用时机,注意以上注释可以单独使用,也可以配合该注解使用,该注解时常配合注解@annotation:用于匹配当前执行方法持有指定注解的方法使用
// 配置织入点
@Pointcut("@annotation(com.ruoyi.common.log.annotation.OperLog)")
public void logPointCut()
{
}
@AfterReturning(pointcut = "logPointCut()")
public void doAfterReturning(JoinPoint joinPoint)
{
handleLog(joinPoint, null);
}
获取节点方法实例或者参数
// 下面两个数组中,参数值和参数名的个数和位置是一一对应的。
Object[] args = joinPoint.getArgs(); // 参数值
String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames(); // 参数名
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method targetMethod = methodSignature.getMethod(); //获取方法实例



