Spring学习笔记_23——切面其他注解
切面中的其他注解
1. @Pointcut注解
@Pointcut
注解可以指定切入点表达式,在使用Spring注解开发AOP程序时,如果需要执行多个通知,并且使用AOP增强的功能确定的情况下,就可以使用@Pointcut注解将切入点表达式通用化。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Pointcut {
// 表示指定的切入点表达式
String value() default "";
// 表示指定的切入点表达式的参数,
// 参数可以是execution中的,也可以是args中的,并且不使用这个属性也可以获得切入点的方法参数
String argNames() default "";
}
2. @Before注解
@Before注解指定方法为前置通知,指定为前置通知的方法在切入点方法之前执行。
在实际开发项目的过程中,如果需要在切入点方法之前执行一些业务逻辑处理,就可以使用@Before注解指定前置通知的方法,让前置通知的方法在切入点方法之前执行。
如果在前置通知的方法中需要获取切入点方法中的参数进行处理时,就需要配合使用切入点表达式参数。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
// 表示指定切入点表达式,可以是表达式,也可以是表达式的引用
String value();
// 表示指定切入点表达式参数的名称。要求和切入点表达式中的参数名称一致。
// 如果不指定切入点表达式参数的名称,一般情况下也可以获取切入点方法的参数内容。
String argNames() default "";
}
3. @After注解
@After注解主要指定最终的通知,如果在实际项目的开发过程中,需要指定最终通知的执行时机,并且需要在切入点方法完成之后执行,无论切入点方法的执行是否抛出异常,都要执行最终的通知方法,就可以使用@After注解标注最终通知的方法。
使用@After注解标注的方法也可以用来执行一些清理工作。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface After {
// 表示指定切入点表达式,可以是表达式,也可以是表达式的引用
String value();
// 表示指定切入点表达式参数的名称。要求和切入点表达式中的参数名称一致。
// 如果不指定切入点表达式参数的名称,一般情况下也可以获取切入点方法的参数内容。
String argNames() default "";
}
4. @AfterReturning注解
@AfterReturning注解可以配置后置增强切入点方法。
在实际项目的开发过程中,比如提交事务、记录访问日志等等功能都可以使用@AfterReturning注解的后置通知实现。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterReturning {
// 表示指定切入点表达式,可以是表达式,也可以是表达式的引用
String value() default "";
// 表示指定切入点表达式,可以是表达式,也可以是表达式的引用
String pointcut() default "";
// 表示指定切入点方法返回值的变量名称,需要注意的是,指定的名称需要和切入点方法返回值名称一致。
String returning() default "";
// 表示指定切入点表达式参数的名称。要求和切入点表达式中的参数名称一致。
// 如果不指定切入点表达式参数的名称,一般情况下也可以获取切入点方法的参数内容
String argNames() default "";
}
5. @AfterThrowing注解
@AfterThrowing
是Spring AOP(面向切面编程)中的一个注解,用于定义一个异常通知(advice),它会在目标方法抛出异常后执行。
这个注解可以确保在方法抛出异常时运行一个通知,这对于异常处理和日志记录非常有用。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterThrowing {
// 一个切入点表达式(pointcut expression),它定义了哪些方法的执行会触发通知(advice)。
// 如果不指定value属性,那么可以使用pointcut属性来指定切入点表达式。
// 默认值为空字符串,意味着如果不设置value,则必须设置pointcut。
String value() default "";
// pointcut 属性同样用于定义切入点表达式,它提供了另一种方式来指定触发通知的方法。
//
String pointcut() default "";
// 用于指定一个参数名,这个参数会作为通知方法的一个参数,代表抛出的异常对象。
// 在通知方法中,你可以通过这个参数名访问到实际抛出的异常。
// 默认值为空字符串,如果未指定,那么在通知方法中将没有代表异常的参数。
String throwing() default "";
}
6. @Around注解
@Around
注解是 AspectJ 框架中的一个切面注解,用于定义环绕通知(around advice)。
它允许你在目标方法执行前后进行一些额外的操作,例如日志记录、性能监控、事务管理等。下面是 @Around
注解的详细介绍和源码。
package org.aspectj.lang.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Around {
// 用于定义切入点表达式,如果不指定,则必须通过 pointcut 属性指定。
String value() default "";
// 用于定义参数名,这是可选的
String argNames() default "";
}
7. Demo
配置类
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
}
定义切面
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
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.ProceedingJoinPoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.Throwable;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
// 定义切入点,匹配com.example.service包下的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}
// 在方法执行前执行
@Before("serviceLayer()")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("Before method: " + joinPoint.getSignature().getName());
}
// 在方法执行后执行
@After("serviceLayer()")
public void afterAdvice() {
System.out.println("After method");
}
// 在方法成功执行后执行
@AfterReturning(pointcut = "serviceLayer()", returning = "result")
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
System.out.println("After method returned: " + result);
}
// 在方法抛出异常后执行
@AfterThrowing(pointcut = "serviceLayer()", throwing = "error")
public void afterThrowingAdvice(JoinPoint joinPoint, Throwable error) {
System.out.println("After method threw exception: " + error.getMessage());
}
// 在方法执行前后执行,可以控制方法的执行
@Around("serviceLayer()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
System.out.println("Method started: " + joinPoint.getSignature().getName());
Object result = joinPoint.proceed();
long timeTaken = System.currentTimeMillis() - startTime;
System.out.println("Method finished: " + joinPoint.getSignature().getName() + " took " + timeTaken + " ms");
return result;
}
}
使用切面
package com.example.service;
import org.springframework.stereotype.Service;
@Service
public class MyService {
public String performAction() {
return "Action performed";
}
public String performActionWithException() throws Exception {
throw new Exception("Something went wrong");
}
}
原文地址:https://blog.csdn.net/LuckyLay/article/details/143490173
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!