【问题标题】:Spring AOP and AspectJ on same methodSpring AOP 和 AspectJ 使用相同的方法
【发布时间】:2021-09-16 10:46:01
【问题描述】:

我有一个关于使用aspectJ和spring aop方法拦截的问题。我创建了 2 个注解:@AJTest@SAOPTest

package com.test.company;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class AJTestAspect {

    @Pointcut("@annotation(AJTest)")
    public void aJTest() {
    }

    @Around("aJTest()")
    public Object profile(ProceedingJoinPoint joinPoint) throws Throwable {
        final long start = System.currentTimeMillis();
        try {
            return joinPoint.proceed();
        } finally {
            long finish = System.currentTimeMillis() - start;
            System.out.println("Method execution time: " + (start - finish));
        }
    }
}

注册了

package com.test.company;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AJConfiguration {

    @Bean
    public AJTestAspect ajTestAspect() {
        return new AJTestAspect();
    }
}

其他

package com.test.company;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class SAOPInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("Number of parameters " + methodInvocation.getArguments().length);
        return methodInvocation.getMethod().invoke(methodInvocation.getThis(), methodInvocation.getArguments());
    }
}

并注册

package com.test.company;

import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties
public class SpringSAOPTestConfiguration {

    @Bean
    public Advisor springAopTestAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("@annotation(com.test.company.SAOPTest)");
        return new DefaultPointcutAdvisor(pointcut, new SAOPInterceptor());
    }
}

并将其添加到我在控制器中的方法中

package com.test.company;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class TestController {
    
        @SAOPTest
        @AJTest
        @GetMapping("/test")
        public String doSomething(@RequestParam("firstParam") String firstParam, @RequestParam("secondParam") Integer secondParam) throws InterruptedException {
            Thread.sleep(2_500);
            return firstParam + " " + secondParam;
        }
    }

应用类

package com.test.company;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@SpringBootApplication
public class AopTestApplication {
    public static void main(String[] args) {
        SpringApplication.run(AopTestApplication.class, args);
    }
}

但是当我通过http://localhost:8080/test?firstParam=test&secondParam=2 调用它时,我看不到方法执行时间的消息,但可以看到传递给方法的参数数量。如果我将删除 @SAOPTest - 方法的执行时间按预期工作,但它不适用于两个注释。是spring创建的代理对象的问题,还是我遗漏了什么?

【问题讨论】:

  • 你可以尝试在切入点表达式中使用注释的完整路径。示例:@annotation(xxx.yyy.abc.AJTest)
  • 同一个包中的所有类,但它不能正常工作@Pointcut("@annotation(com.test.company.AJTest)")
  • 你是怎么运行这个的?你有多个配置?那些是如何加载的?这是 Spring Boot 还是普通 Spring 或 ... 对于 @AspectJ,您还需要在配置中使用 @EnableAspectJAutoProxy(如果这不是 Spring Boot 应用程序)。
  • 这是带有 1 个端点的示例的 spring-boot 演示项目
  • 请在您的源代码中包含软件包并包含您的@SpringBootApplication 注释类。

标签: java spring spring-boot aspectj spring-aop


【解决方案1】:

您的拦截器没有正确进行。请阅读MethodInterceptor javadoc。拦截器应如下所示:

public class SAOPInterceptor implements MethodInterceptor {
  @Override
  public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    System.out.println("Number of parameters " + methodInvocation.getArguments().length);
    return methodInvocation.proceed();
  }
}

此外,您的方面也计算错误的时间。首先,你说finish = System.currentTimeMillis() - start,然后你打印start - finish。您应该减去finish - start 或计算在变量中花费的时间,但不能同时减去start - finish。为什么不直接System.out.println("Method execution time: " + (System.currentTimeMillis() - start));

【讨论】:

  • 非常感谢proceed() 而不是method.invoke() 解决了这个问题。是的,我知道计算是错误的,问题是为什么我对 aspectj 的注释被 spring aop 方法拦截器抑制了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 1970-01-01
相关资源
最近更新 更多