Spring AOP – 使用 Aspectj
使用 Aspectj 注解实现各种通知
@Before:前置通知,在方法执行前执行
@After:后置通知,在方法执行后通知
@AfterRunning:返回通知,在方法返回结果后通知
@AfterThrowing:异常通知:在方法抛出异常后通知
@Around:环绕通知:围绕着方法执行
需要以下jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectjrt.version}</version>
</dependency>
创建接口与实现类,并交给 Spring 管理
public interface ArithmeticCalculator {
int add(int i, int j);
int div(int i, int j);
}
@Component
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
@Override
public int add(int i, int j) {
int result = i + j;
System.out.println("result:" + result);
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
System.out.println("result:" + result);
return result;
}
}
在Spirng配置里加入:
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.java.spring.aop"></context:component-scan>
使用 Aspectj 注解来实现前置通知
//把该类声明为一个切面:需要先将类放入到 IOC 容器中 ,再声明为一个切面
@Aspect
@Component
public class Logging {
/*
声明该方法是一个 前置通知:在目标方法开始前执行
execution(* com.java.spring.aop.impl.*.*()) 中表示任意修饰符,任意返回值,
在com.java.spring.aop.impl 包下任意类中的任意方法
*/
@Before("execution(* com.java.spring.aop.impl.*.*(int,int))")
//可以在方法里声明类型为 JoinPoint 的参数,获得连接点的细节,如方法名称和参数值
public void beforLogin(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName(); //获取方法名称
List<Object> args = Arrays.asList(joinPoint.getArgs()); //获取方法参数值
System.out.println("method " + methodName + " begins " + args);
}
}
执行结果如下
method add begins [3, 6]
result:9
method div begins [12, 3]
result:4
使用 Aspectj 注解来实现后置通知
//在方法执行后,执行通知(无论是否发送异常)
@After("execution(* com.java.spring.aop.impl.*.*(int,int))")
public void afterLogin(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
System.out.println("method " + methodName);
}
执行结果如下
result:9
method add end
result:4
method div end
注意:即便发生异常,依然会执行:
使用 Aspectj 注解来实现返回通知
//在方法正常结束后执行,可以访问到方法的返回值
@AfterReturning(value = "execution(* com.java.spring.aop.impl.*.*(int,int))",returning = "result")
public void afterReturningLogin(JoinPoint joinPoint , Object result){
String methodName = joinPoint.getSignature().getName();
System.out.println("method " + methodName+" result " + result);
}
执行结果如下
result:9
method add result 9
result:4
method div result 4
使用 Aspectj 注解来实现异常通知
//在方法出现异常时执行,可以访问到异常对象,且可以指定特定异常在执行通知
@AfterThrowing(value = "execution(* com.java.spring.aop.impl.*.*(int,int))",throwing = "ex")
public void afterThrowingLogin(JoinPoint joinPoint , Exception ex){
String methodName = joinPoint.getSignature().getName();
System.out.println("method " + methodName+" exception " + ex);
}
执行结果如下
使用 Aspectj 注解来实现环绕通知
/*
环绕通知需要有 ProceedingJoinPoint 这个参数,这个参数可以决定是否执行目标方法
环绕通知必须有返回值,返回值为目标方法返回值
*/
@Around("execution(* com.java.spring.aop.impl.*.*(int,int))")
public Object aroundLogin(ProceedingJoinPoint pjd ){
Object result = null;
String methodName = pjd.getSignature().getName();
try {
//前置通知
System.out.println("method " + methodName + " begins " + Arrays.asList(pjd.getArgs()));
//执行目标方法
result = pjd.proceed();
//返回通知
System.out.println("method " + methodName+" result " + result);
} catch (Throwable e) {
//异常通知
System.out.println("method " + methodName+" exception " + e);
}
//后置通知
System.out.println("method " + methodName+" end ");
return result;
}
执行结果如下
发生异常后如下