spring如何让方法不走切面

worktile 其他 134

回复

共3条回复 我来回复
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    为了让方法不走切面,我们可以使用Spring AOP的exclude和include标签来控制切面的应用范围。下面分别介绍如何使用这两个标签来实现对方法的切面控制。

    1. 使用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的方法。这样就可以实现对特定方法的排除。

    1. 使用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年前 0条评论
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    在Spring中,我们可以通过以下方法让方法不走切面:

    1. 使用@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方法判断是否需要执行切面逻辑,如果不需要,则直接跳过切面逻辑,直接执行被拦截的方法。

    1. 在切面定义中使用条件判断语句。通过在切面定义中使用条件判断语句,我们可以根据不同的条件选择是否执行切面逻辑。
    @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)条件判断注解是否存在,如果不存在则执行切面逻辑。

    1. 使用@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为切入点,只有满足该切入点条件的方法才会执行切面逻辑。

    1. 使用@Order注解来控制切面的执行顺序。在应用程序中可能存在多个切面,通过使用@Order注解,我们可以控制切面的执行顺序。
    @Aspect
    @Order(1)
    public class MyAspect1 {
        // ...
    }
    
    @Aspect
    @Order(2)
    public class MyAspect2 {
        // ...
    }
    

    在上面的代码中,MyAspect1的执行顺序高于MyAspect2,因此MyAspect1的切面逻辑会在MyAspect2之前执行。

    1. 使用@Aspect注解的perthis属性来控制切面的实例化方式。通过设置perthis属性为“self”,我们可以控制切面实例化的方式,
      即每个被切方法调用都会实例化一个新的切面对象,这样可以避免不需要应用切面的方法。
    1年前 0条评论
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    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年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部