java - 使用字节伙伴代理按AspectJ检测编织的类

标签 java aspectj agent byte-buddy

我想验证代码是否由AspectJ编写。我听说过的一种方法是使用字节伙伴库中的代理。不幸的是,我完全是绿色的,我不知道该怎么办。

我尝试将JADE与代理一起使用,但是字节伙伴对我自己更友好,我认为它更合适。

为了验证该方法,我创建了一个带有MySQL连接的简单springboot应用程序,并添加了一些AspectJ代码。我尝试使用Spring AOP,但是AOP无法读取私有方法,因此我决定将我的想法与AspectJ一起提供。

我已经使用了另一个方面来定义joinPoints并引发异常,但是这很困难并且需要很多工作并且结果很低。

您对使用字节伙伴检测AspectJ的代理的方法或实现有任何想法吗?

最佳答案

首先回答您的评论:


我想对不可信的代码有更多的经验。例如,如果我用Java开发了一个大型项目,然后得到了一些由AspectJ创建的更改的不受信任的插件,那么我更愿意知道该怎么做才能检查我的类是否受AspectJ的保护或AspectJ只是编织到我的类中。


对于AspectJ,有两种情况:


编译时编织


您的应用程序不使用AspectJ,在Maven构建中不使用AspectJ Maven插件,也不在Gradle构建中使用类似的东西:即使您的第三方库位于类路径中,也没有任何东西编入您自己的代码中。怎么可能没有AspectJ编译器。
您的应用程序使用AspectJ编译器:即使第三方库位于类路径中,也没有将方面编织到您自己的代码中,因为您必须将库明确地放在方面路径中才能实现。顺便说一句,如果第三方库是方面增强的,它将依赖于AspectJ运行时Aspectjrt.jar,否则它将无法工作。即使运行时被隐藏在其他JAR中,您自己的代码也不会发生任何事情。

加载时间编织


您的应用程序不使用LTW:显然不会发生任何事情,如果您不使用活动的编织代理启动JVM,则其他JAR的任何方面都无法编织到您的代码中。
您的应用程序使用LTW:您将需要提供aop.xml文件,并且您可以在此处明确列出要应用的方面,哪些目标类或包要包含到编织中或从编织中排除,请打开-showWeaveInfo以便也能看到在控制台上将哪些方面编织到哪些连接点中。但是,有一个警告:如果AspectJ编织者在类路径上找到多个aop.xml或aop-ajc.xml文件,它将在概念上合并它们。即如果第三方库随附了此类文件,则该文件将按照AspectJ development guide中的说明合并到您自己的文件中(在页面上搜索“多个配置文件”)。因此,这可能会导致一些不良后果。如果要检查第三方库,最简单的操作是分别扫描JAR中是否存在aop.xml或aop-ajc.xml。然后,您可以查看这些文件的内容(如果有),并轻松评估它们对代码的可能影响。但是,只要在应用程序启动时检查-showWeaveInfo的输出,还可以发现是否将不需要的方面编织到了自己的代码中。





因此,实际上您不需要扫描类文件中的任何内容即可检测AspectJ标记,但是如果您绝对希望这样做,可以执行以下操作:

大多数AspectJ编织的类都包含字段或方法(可以是静态或非静态,私有或公共的),其名称中通常在开头带有ajc$。那只是一种启发式方法,但是嘿-不管用什么,对不对?


如果我说“大多数类”,则是指在某些情况下,如果某个方面仅使用ITD来使一个类实现接口,引入新方法或公共字段,则该类将仅获取新元素,而没有AspectJ专用代码。但是,它们只是普通的类,没有交叉的建议代码或任何可能影响您自己的应用程序的代码。
如果您找到这样的成员或字段,则表明您或者找到了由方面增强的类(即使在带有额外aop.xml的LTW场景中也不会影响您自己的类)或方面本身,因为它们还包含相同的标记,您可以扫描的其他一些东西。


那么,如何扫描这些第三方类文件?


命令行:javap -p path/to/MyClass.class | grep 'ajc[$]'
扫描已经加载到(测试或检查)应用程序中的类的Java代码:


package de.scrum_master.aspect;

import java.lang.reflect.Member;
import java.util.stream.Stream;

public class AspectJDetector {
  public static boolean hasAspectJMarker(Class<?> clazz) {
    return Stream.concat(
      Stream.of((Member[]) clazz.getDeclaredMethods()),
      Stream.of((Member[]) clazz.getDeclaredFields())
    )
      .filter(member -> member.getName().contains("ajc$"))
      .findFirst()
      .isPresent();
  }
}


只需为要检查的每个班级拨打hasAspectJMarker(MyClassOfInterest.class)。如果您找到了AspectJ增强的类,则无需担心。只有找到方面,才有可能。但是正如我上面所说:通过该JAR中的aop.xml可以更容易地检测到它。 XML文件甚至可以通过<aspect name="com.MyAspect"/>明确列出各个方面,这基本上是显而易见的。

关于java - 使用字节伙伴代理按AspectJ检测编织的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57811860/

相关文章:

java - Jetty设置Servlet与JSP页面通信

java - Windows 上的虚假唤醒。是否可以?

Azure管道条件选择槽代理

java - Spring AOP 与 AspectJ

java - 在另一个方法中调用一个方法后执行一些操作

java - 代理在多代理系统中的行为?

f# - 在远程邮箱处理器之间传递消息?

java - 在 Eclipse 中复制/粘贴/复制 java 文件

java - 如何对 ElementCollection 和 CollectionTable 使用 CriteriaQuery

java - Jetty 和 Java 代理无法使用日志记录工作