spring在使用aop类级别注释时为错误的类创建代理

2023-11-30

当使用 spring AOP 和类级别注释时,springcontext.getBean似乎总是为每个类创建并返回一个代理或拦截器,无论它们是否有注释。

此行为仅适用于类级别注释。对于方法级别的注解,或者执行切入点,如果不需要拦截,getBean返回一个 POJO。

这是一个错误吗?按照设计?或者我做错了什么?

@Component
@Aspect
public class AspectA {
  @Around("@target(myAnnotation)")
  public Object process(ProceedingJoinPoint jointPoint, MyAnnotation myAnnotation) throws Throwable {
    System.out.println(
      "AspectA: myAnnotation target:" + jointPoint.getTarget().getClass().getSimpleName());
    System.out.println(" condition:" + myAnnotation.condition());
    System.out.println(" key:" + myAnnotation.key());
    System.out.println(" value:" + myAnnotation.value());
    return jointPoint.proceed();
  }
}
@Component("myBean2")
//@MyAnnotation(value="valtest-classLevel2", key="keytest-classLevel2", condition="contest-classLevel2")
public class MyBean2 {
  public Integer testAspectCallInt(int i) {
    System.out.println("MyBean2.testAspectCallInt(i=" + i + ")");
    return i + 1000;
  }
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface MyAnnotation {
  String value() default "";
  String key() default "";
  String condition() default "";
}
@ComponentScan()
@EnableAspectJAutoProxy
public class Test {
  public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(Test.class);
    MyBean2 bean = (MyBean2) ctx.getBean("myBean2");
    System.out.println(bean.getClass());  // prints CGLIB proxy, even when annotation is commented out on class
    bean.testAspectCallInt(12); // calling method
  }
}

安迪·布朗是对的,这是设计使然。原因是,根据AspectJ手册切入点指示符,例如@args, @this, @target, @within, @withincode, and @annotation(或者 Spring AOP 中可用的子集)用于根据注释的存在进行匹配runtime。这就是为什么在 Spring 调试日志中您会看到为所有可能需要方面功能的组件创建了代理。

如果您想避免这种情况,您可以将方面重构为类似的内容,但代价是在建议代码中出现更丑陋的切入点甚至更丑陋的反射:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;

@Component
@Aspect
public class AspectA {
  @Around("execution(* (@MyAnnotation *).*(..)) || execution(@MyAnnotation * *(..))")
  public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
    MyAnnotation myAnnotation = null;
    for (Annotation annotation : ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaredAnnotations()) {
      if (annotation instanceof MyAnnotation) {
        myAnnotation = (MyAnnotation) annotation;
        break;
      }
    }
    if (myAnnotation == null) {
      myAnnotation = joinPoint.getTarget().getClass().getAnnotationsByType(MyAnnotation.class)[0];
    }
    System.out.println("AspectA: myAnnotation target:" + joinPoint.getTarget().getClass().getSimpleName());
    System.out.println(" condition:" + myAnnotation.condition());
    System.out.println(" key:" + myAnnotation.key());
    System.out.println(" value:" + myAnnotation.value());
    return joinPoint.proceed();
  }
}

如果 bean 的类及其任何方法都不带有注释,则不会创建代理。该建议会检测两种类型的注释,但如果两者都存在,则更喜欢方法注释。

Update:除了这种解决方法之外,您当然可以在 Spring 中使用完整的 AspectJ 并完全避免代理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring在使用aop类级别注释时为错误的类创建代理 的相关文章

随机推荐

  • 使用 $map 进行 MongoDB 嵌套数组搜索

    我有包含嵌套数组的集合 我需要根据以下条件获取数据 empId 19107 address country AUS group primaryGroup primary Y group subGroup primarySubGroup pr
  • Rxjs - DistinctUntilChanged() 与 keyup 事件

    我正在使用 Rxjs 6 它根据表单字段中的 keyup 事件过滤 Firebase 返回的可观察值 当用户在表单字段中没有值的情况下不断按退格键时 我遇到一个问题 然后看起来可观察对象不断刷新 使用 DistinctUntilChange
  • 在 HBase 之上的 solr 中创建索引

    无论如何 我可以在 Solr 中创建索引来从 HBase 执行近实时全文搜索 我不想将整个文本存储在我的 solr 索引中 制成 stored false 注意 请记住 我正在处理大型数据集 并且想要进行近实时搜索 我们正在谈论 TB PB
  • 格式化字典键:AttributeError:'dict'对象没有属性'keys()'

    在字符串中格式化字典键的正确方法是什么 当我这样做时 gt gt gt foo one key one value second key second value gt gt gt In the middle of a string foo
  • 生成并下载网页截图而不丢失样式

    我想生成并下载网页的屏幕截图而不丢失样式 我有一个网页 在该网页中我有一个下载按钮 当用户单击下载按钮时 整个页面的屏幕截图需要作为图像下载到用户计算机中 我怎样才能做到这一点 请检查我的代码 索引 html h1 Scrrenshot h
  • 在用作指针的结构中嵌入结构与指向结构的指针

    如果我有一个结构类型A用作指针 仅具有指针接收器 构造函数返回 A等 嵌入结构类型有什么区别B as B versus B 也就是说 有什么区别 type B struct type A struct B and type B struct
  • Windows XP 上有多个版本的 Safari? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 有没有办法在Windows XP下运行多个版本的Safari 我有兴趣运行 Safari 版本 3 1 和 4 具体来说 我想用 Safari 3 1 调试此类问题 但在我当前的版本
  • Python - 如何将 ttkthemes 包中的主题添加到 guizero 应用程序?

    我正在开发多个 guizero 项目 并且尝试从 Python 包 ttkthemes 添加主题 准确地说是 arc 我尝试使用以下代码将主题添加到应用程序小部件 from guizero import App Text PushButto
  • 相机捕获图像的形状检测(圆形、正方形、矩形、三角形、椭圆形)+ iOS 5 + Open CV

    我是 OpenCV 新手 需要了解 OpenCV 检测 iPhone 相机拍摄图像中不同形状 圆形 正方形 矩形 三角形 椭圆形 的方法 那么 有人可以指导我正确的方向 参考文献 文章 任何东西 哪些技术可以更好地完成它 Thanks iO
  • Haskell 函数的参数数量

    当我尝试用以下命令编译它时ghc它抱怨函数定义左侧的参数数量不同 module Example where import Data Maybe from maybe a gt Maybe a gt a from maybe a Nothin
  • Python:Plt 条形图 - 不同颜色

    在Python中 我怎样才能使 reported 绿色条形 以及 UNREPORTED 酒吧红色 我想为图表中每个已报告和未报告的条形赋予不同的颜色 new AXIN 37 reported LGR 30 UNREPORTED NKD 24
  • YouTube iframe 事件

    我尝试捕获 YouTube iframe 的事件 http lab joergpfeiffer de videofull youtube php 所以我首先调用api 我设置了 iframe
  • 具有重复的递归排列

    我正在尝试编写一个递归函数 该函数通过给定列表的重复来获取所有排列 Eg set ABC 1 AAA 2 AAB 3 AAC 4 ABA N CCC 我想要此代码的递归版本 以便我可以获得任何大小的集合的排列 for i 0 i
  • 0..9 约束在 GCC 内联汇编中起什么作用?

    手册 says 允许使用与指定操作数编号匹配的操作数 如果一个数字 在同一个选项中与字母一起使用 数字应该放在最后 我不确定这意味着什么 示例代码 asm volatile swap 0 r value 0 value 堆栈溢出的内联汇编标
  • Chrome 扩展程序仅在单击某些网页时起作用

    我正在尝试让我的 Chrome 扩展程序在用户打开时弹出警报http google com 并单击扩展图标 我有以下清单 manifest version 2 name One Megahurt version 0 1 permission
  • 我想制作一个像 WhatsApp 个人资料照片对话框屏幕一样的对话框屏幕

    大家好 我目前正在尝试使用隐式意图创建一个对话框 我想在其中显示我的对话框 例如 WhatsApp 个人资料照片屏幕 并且在此屏幕中 WhatsApp 使用名为 删除照片 的额外字段 当我尝试制作相同类型的屏幕对话框时 我无法添加此额外字段
  • 如何更改 vue-cli 的分隔符?

    我安装了 vue cli webpack simple src main js import Vue from vue import App from App vue new Vue delimiters here delimiters s
  • 为 Javascript 制作文件

    有人可以告诉我如何使用 make 文件来组合和合并不同的 javascript 文件 我见过许多不同的项目使用不同的 javascript 文件 后来使用 MAKE 实用程序进行合并 Deep None
  • Java Swing —— 编写一个可根据自定义数据对象的更改重新绘制自身的 Ui

    首先 我已经发布了一个问题earlier其中我曾就为什么我的代码无法工作而寻求帮助 并且这个问题是根据我在该问题中得到的建议采取的 我的用例是这样的 我正在写一个MethodEditor模块其中每个Method由具有 2 个数据成员的自定义
  • spring在使用aop类级别注释时为错误的类创建代理

    当使用 spring AOP 和类级别注释时 springcontext getBean似乎总是为每个类创建并返回一个代理或拦截器 无论它们是否有注释 此行为仅适用于类级别注释 对于方法级别的注解 或者执行切入点 如果不需要拦截 getBe