【问题标题】:Unable to retrieve annotation via ProceedingJoinPoint无法通过 ProceedingJoinPoint 检索注释
【发布时间】:2023-03-21 18:07:01
【问题描述】:

我想从 AOP 连接点检索注释。我可以通过反射获得注释,但无法通过 ProceedingJoinPoint 获得。

如果该方法未使用 Profile 进行注释,则不会调用通知...但在通知内,它无法找到注释。

通过 ProceedingJoinPoint

@Around("@annotation(com.annotation.Profile)")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    Signature signature = joinPoint.getSignature();
    String methodName = signature.toString();
    Method method = ((MethodSignature) signature).getMethod();

    Profile profile = method.getAnnotation(Profile.class);

    // profile is null here...
    // ......

}   

直接反射

public static void main(String[] args) throws NoSuchMethodException, SecurityException {
    Method method = SampleServiceImpl.class.getMethod("getTicket", String.class);
    System.out.println(method.getClass().toString());
    System.out.println(method.getAnnotation(Profile.class));
}

我的注释

@Documented
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Profile {
    public long skipCount();
    public long sampleSize();
}

我的注释方法

@Override
@Cacheable("test")
@Transactional
@Profile(skipCount = 100, sampleSize = 100)
public Tickets getTicket(String ticketId) {
    return sampleDao.getTicket(ticketId);
}

我的 POM

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <jdk.version>1.8</jdk.version>
    <spring.version>4.1.1.RELEASE</spring.version>
    <aspectj.version>1.8.3</aspectj.version>
</properties>

<!-- Spring AOP + AspectJ -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

【问题讨论】:

    标签: annotations aop aspectj spring-aop


    【解决方案1】:

    不需要反思,要容易得多。您可以将注解绑定到通知参数:

    @Around("@annotation(profileAnnotation)")
    public Object logAround(Profile profileAnnotation, ProceedingJoinPoint thisJoinPoint) throws Throwable {
        System.out.println(thisJoinPoint + " - " +  profileAnnotation);
        // (...)
        Object result = thisJoinPoint.proceed();
        // (...)
        return result;
    }
    

    控制台输出可能是这样的:

    execution(void de.scrum_master.app.Application.main(String[])) - @de.scrum_master.app.Profile(skipCount=5, sampleSize=11)
    

    【讨论】:

    • 谢谢。启用 GCLIB 后,我可以从之前显示的代码中获取注释。请问启用GCLIB有什么缺点吗?
    • 您的意思是与 Java 动态代理相比吗?通常,Java 代理仅适用于接口,CGLIB 也适用于需要代理而无需接口的类。否则我对它们中的任何一个都没有太多的实践经验,因为我只使用根本不需要任何代理的原生 AspectJ。 Spring AOP 只是基于代理的“AOP lite”,不是我的选择。
    • 方法参数的顺序要颠倒,我对提供的代码做了修改。
    • 我不明白你的评论。我在您的问题中没有看到任何编辑,我自己的编辑是最后一个。什么被逆转了?它将如何影响我的回答?
    • 是的,我试过了。仅当我将关节点作为第一个参数时它才有效,否则它会引发异常。不确定这是否与我使用的版本有关
    猜你喜欢
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    相关资源
    最近更新 更多