Spring Aop
.
1).需要加入jar包
aopalliance-.jar
aspectjweaver-1.9.1.jar
commons-logging-1.2.jar
spring-aop-5.0.9.RELEASE.jar
spring-aspects-5.0.9.RELEASE.jar
spring-beans-5.0.9.RELEASE.jar
spring-context-5.0.9.RELEASE.jar
spring-core-5.0.9.RELEASE.jar
spring-expression-5.0.9.RELEASE.jar
2).在配置文件中加入aop的命名空间
3).基于注解的方式
⭕在配置文件中加入如下配置
aop:aspectj-autoproxy</aop:aspectj-autoproxy>
⭕把横切关注点的代码抽象到切面的类中
Ⅰ. 切面首先是一个IOC容器中的bean,即加入@component注解
Ⅱ .切面还需要加入@Aspect注解
⭕在类中声明各种通知
——@Before:前置通知,在方法执行之前执行
——@After:后置通知,在方法执行之后执行
——@AfterRunning:返回通知,在方法返回结果之后执行
——@AfterThrowing:异常通知,在方法抛出异常之后
——@Around:环绕通知,围绕着方法执行
⭕可以在通知方法中声明一个类型为JoinPoint的参数,然后就能访问连接细节,如方法的名称和参数值
package com.spring.learning.aop.impl;
import java.util.Arrays;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/*
* 把这个类声明为一个切面:
* @Component:把该类放置在IOC容器中
* @Aspect:声明为一个切面
* @order:指定切面的优先级,值越小,优先级越高
* */
@Order(2)
@Component
@Aspect
public class LoggingAspect {
/*
*定义一个方法,用于声明切入点表达式。一般的,该方法中不再需要填入其他代码
*使用 @Pointcut 来声明切入点表达式。
*后面的其他通知直接使用方法名来引用当前的切入点表达式。
* */
@Pointcut("execution(public int com.spring.learning.aop.impl.ArithmeticCalculator.*(int, int))")
public void declareJoinPointExpression() {}
/*
* 前置通知:在目标方法开始之前执行
* */
@Before("declareJoinPointExpression()")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The method "+methodName+" begins with "+Arrays.asList(joinPoint.getArgs()));
}
/*
* 后置通知:在目标方法执行后(无论是否发生异常),执行的通知
* 在后置通知中还不能访问目标方法执行的结果
*/
@After("declareJoinPointExpression()")
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The metod "+methodName+" ends");
}
/*
* 返回通知:在方法正常结束后执行的代码
* 返回通知是可以访问到方法的返回值的!
* */
@AfterReturning(value="declareJoinPointExpression()",returning="result")
public void afterReturningMethod(JoinPoint joinPoint,Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The metod "+methodName+" ends with "+result);
}
/*
* 异常通知:在目标方法出现异常时执行的代码
* 可以访问到异常对象;且可以指定在出现特定异常时再执行通知代码
* */
@AfterThrowing(value="declareJoinPointExpression()",throwing="ex")
public void afterThrowingMethod(JoinPoint joinPoint,Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println("The metod "+methodName+" occurs with: "+ex);
}
/*
* 环绕通知(功能最强但是不一定最常用):需要携带 ProceedingJoinPoint 类型的参数
* 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
* 且环绕通知必须有返回值,返回值即为目标方法的返回值
* */
/* @Around("declareJoinPointExpression()")
public Object aroundMethod(ProceedingJoinPoint pjd) {
Object result = null;
String methodName = pjd.getSignature().getName();
try {
//前置通知
System.out.println("The method "+methodName+" begins with" + Arrays.asList(pjd.getArgs()));
//执行目标方法
result = pjd.proceed();
//返回通知
System.out.println("The method "+methodName+" ends with " +result);
} catch (Throwable e) {
// TODO Auto-generated catch block
System.out.println("The method "+methodName+" occurs exception:"+e);
e.printStackTrace();
throw new RuntimeException(e);
}
//后置通知
System.out.println("The method " +methodName+" ends");
return 100;
}*/
}