spring如何让方法不走切面
-
为了让方法不走切面,我们可以使用Spring AOP的exclude和include标签来控制切面的应用范围。下面分别介绍如何使用这两个标签来实现对方法的切面控制。
- 使用exclude标签
exclude标签可以用来指定不需要被切面拦截的方法。可以在切面的定义中通过exclude标签来指定不需要拦截的方法。示例如下:
@Aspect public class MyAspect { @Around("execution(* com.example.service.*.*(..)) && !execution(* com.example.service.*.foo(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { // 切面逻辑处理 return joinPoint.proceed(); } }上面的例子中,切面MyAspect会拦截com.example.service包中的所有方法,除了名为foo的方法。这样就可以实现对特定方法的排除。
- 使用include标签
include标签可以用来指定需要被切面拦截的方法。可以在切面的定义中通过include标签来指定需要拦截的方法。示例如下:
@Aspect public class MyAspect { @Around("execution(* com.example.service.*.bar(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { // 切面逻辑处理 return joinPoint.proceed(); } }上面的例子中,切面MyAspect只会拦截com.example.service包中名为bar的方法。这样就可以实现对特定方法的包含。
通过使用exclude和include标签,我们可以精确控制切面的应用范围,实现对指定方法的切面排除或包含。
1年前 - 使用exclude标签
-
在Spring中,我们可以通过以下方法让方法不走切面:
- 使用@Around注解来控制切面的执行流程。@Around注解可以在方法执行前和执行后进行拦截,并决定是否继续执行方法。
@Around("execution(* com.example.demo.service.*.*(..))") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { // TODO: 判断是否需要执行切面逻辑,如果不需要,则直接跳过切面逻辑 if (shouldSkip(joinPoint)) { return joinPoint.proceed(); } // 执行切面逻辑 // ... // 执行被拦截的方法 return joinPoint.proceed(); }在上面的代码中,我们可以通过shouldSkip方法判断是否需要执行切面逻辑,如果不需要,则直接跳过切面逻辑,直接执行被拦截的方法。
- 在切面定义中使用条件判断语句。通过在切面定义中使用条件判断语句,我们可以根据不同的条件选择是否执行切面逻辑。
@Before("execution(* com.example.demo.service.*.*(..)) && !@target(com.example.demo.annotation.SkipAspect)") public void before(JoinPoint joinPoint) { // TODO: 判断是否需要执行切面逻辑,如果不需要,则直接return if (shouldSkip(joinPoint)) { return; } // 执行切面逻辑 // ... }在上面的代码中,我们通过!@target(com.example.demo.annotation.SkipAspect)条件判断注解是否存在,如果不存在则执行切面逻辑。
- 使用@Pointcut注解来指定切入点。通过使用@Pointcut注解,我们可以在切面定义中指定切入点,只有满足指定条件的方法才会执行切面逻辑。
@Pointcut("execution(* com.example.demo.service.*.*(..)) && !@annotation(com.example.demo.annotation.SkipAspect)") public void executionPointcut() {} @Before("executionPointcut()") public void before(JoinPoint joinPoint) { // 执行切面逻辑 // ... }在上面的代码中,我们通过指定executionPointcut为切入点,只有满足该切入点条件的方法才会执行切面逻辑。
- 使用@Order注解来控制切面的执行顺序。在应用程序中可能存在多个切面,通过使用@Order注解,我们可以控制切面的执行顺序。
@Aspect @Order(1) public class MyAspect1 { // ... } @Aspect @Order(2) public class MyAspect2 { // ... }在上面的代码中,MyAspect1的执行顺序高于MyAspect2,因此MyAspect1的切面逻辑会在MyAspect2之前执行。
- 使用@Aspect注解的perthis属性来控制切面的实例化方式。通过设置perthis属性为“self”,我们可以控制切面实例化的方式,
即每个被切方法调用都会实例化一个新的切面对象,这样可以避免不需要应用切面的方法。
1年前 -
Spring框架提供了AOP(面向切面编程)的功能,它可以让我们在方法执行的前后加入额外的逻辑,比如日志记录、权限校验等。但是有时候,我们可能希望某些方法不被切面影响,这篇文章将介绍几种方法来实现这个需求。
一、使用@Before和@After注解控制切面执行的顺序
使用@Before和@After注解可以控制切面的执行顺序,我们可以给某些方法添加一个特殊的注解,用来标识它们不需要被切面影响。首先,定义一个自定义的注解,比如@ExcludeAspect:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExcludeAspect { }然后,在切面类中,通过@Before和@After注解指定切面执行的顺序,并在切面方法上添加一个判断条件,判断方法上是否存在@ExcludeAspect注解:
@Aspect @Component public class MyAspect { // 定义一个切面方法,在目标方法执行之前执行 @Before("execution(* com.example.service.*.*(..))") public void before(JoinPoint joinPoint) { // 判断方法上是否存在@ExcludeAspect注解 if (!joinPoint.getTarget().getClass().isAnnotationPresent(ExcludeAspect.class)) { // 执行切面逻辑 // ... } } // 定义一个切面方法,在目标方法执行之后执行 @After("execution(* com.example.service.*.*(..))") public void after(JoinPoint joinPoint) { // 判断方法上是否存在@ExcludeAspect注解 if (!joinPoint.getTarget().getClass().isAnnotationPresent(ExcludeAspect.class)) { // 执行切面逻辑 // ... } } }最后,在需要不被切面影响的方法上添加@ExcludeAspect注解:
@Service public class MyService { public void method1() { // ... } @ExcludeAspect public void method2() { // ... } }这样,切面将不会对带有@ExcludeAspect注解的方法进行拦截。
二、使用切点表达式控制切面的作用范围
切点表达式是AOP中用来定义切入点(即需要被切面拦截的方法)的规则。我们可以使用切点表达式来控制切面的作用范围,不包括某些特定的方法。在切面类中,使用@Pointcut注解定义一个切入点,然后在切面方法上使用@Pointcut注解指定切入点表达式,排除不需要被切面拦截的方法:
@Aspect @Component public class MyAspect { // 定义一个切入点,拦截com.example.service包下的所有方法,除了method2方法 @Pointcut("execution(* com.example.service.*.*(..)) && !execution(* com.example.service.MyService.method2(..))") public void pointcut() { } // 定义一个切面方法,在切入点方法执行之前执行 @Before("pointcut()") public void before(JoinPoint joinPoint) { // 执行切面逻辑 // ... } // 定义一个切面方法,在切入点方法执行之后执行 @After("pointcut()") public void after(JoinPoint joinPoint) { // 执行切面逻辑 // ... } }这样,切面将不会对method2方法进行拦截。
三、在切面方法内部判断方法名
我们也可以在切面方法内部对方法名进行判断,如果是需要不被切面拦截的方法,则不执行切面逻辑。在切面类中,判断方法名是否需要被排除:
@Aspect @Component public class MyAspect { // 定义一个切面方法,在目标方法执行之前执行 @Before("execution(* com.example.service.*.*(..))") public void before(JoinPoint joinPoint) { // 获取方法名 String methodName = joinPoint.getSignature().getName(); // 判断方法名是否需要被排除 if (!methodName.equals("method2")) { // 执行切面逻辑 // ... } } // 定义一个切面方法,在目标方法执行之后执行 @After("execution(* com.example.service.*.*(..))") public void after(JoinPoint joinPoint) { // 获取方法名 String methodName = joinPoint.getSignature().getName(); // 判断方法名是否需要被排除 if (!methodName.equals("method2")) { // 执行切面逻辑 // ... } } }这样,切面将不会对名为method2的方法进行拦截。
四、使用Java配置控制切面的执行顺序
如果你使用的是Java配置方式配置切面,可以借助Order接口来控制切面的执行顺序。首先,创建一个OrderAspect类,实现Order接口,并在切面方法上使用@Order注解指定切面的顺序:
@Aspect @Component @Order(1) public class OrderAspect implements Ordered { @Before("execution(* com.example.service.*.*(..))") public void before(JoinPoint joinPoint) { // 执行切面逻辑 // ... } @After("execution(* com.example.service.*.*(..))") public void after(JoinPoint joinPoint) { // 执行切面逻辑 // ... } @Override public int getOrder() { return 1; } }然后,创建一个AnotherAspect类,不实现Order接口,默认的切面顺序为0:
@Aspect @Component public class AnotherAspect { @Before("execution(* com.example.service.*.*(..))") public void before(JoinPoint joinPoint) { // 执行切面逻辑 // ... } @After("execution(* com.example.service.*.*(..))") public void after(JoinPoint joinPoint) { // 执行切面逻辑 // ... } }这样,OrderAspect将先于AnotherAspect执行。
通过以上几种方法,我们可以实现让某些方法不走切面的需求。根据具体场景,选择合适的方法来控制切面的作用范围。
1年前