gpt4 book ai didi

java - AOP 检测 Hibernate.unproxy() 的所有类转换

转载 作者:行者123 更新时间:2023-12-01 11:08:28 26 4
gpt4 key购买 nike

我希望能够编写一个方面来检测我何时在我的 org.mypackage 中转换某些东西类。

package org.mypackage;

class Foo {
public static void main(String[] args) {
Bar casted = (Bar) args[0]; // want to detect this casting action!
}
}

你怎么写一个切入点来表达强制转换操作,不只是为了 Foo类,但对于 org.mypackage 中的任何类?

背景:所以 Hibernate 5 + Spring Data JPA 需要通过继承来转换实体:
if (isInstanceOfMyEntity(someEntity)) {
// formerly, this was sufficient:
// MyEntity myEntity = (MyEntity) someEntity;
// now, this is required *everywhere* it is casted:
MyEntity myEntity = (MyEntity) Hibernate.unproxy(someEntity);
...
}

...在大型代码库中,考虑这点很可怕,因为这可能会破坏很多地方。因此,如果可以编写一个切面/切入点来至少检测它,那么我们至少可以记录它并确定测试中需要解决问题的位置。

在这个问题中推荐了这种技术 How to convert a Hibernate proxy to a real entity object通过@Vlad-Mihalcea。

最佳答案

对于 Spring AOP 和 AspectJ,答案都是:你不能拦截 Actor 。 没有像这样细粒度的切入点。

背景:这也没有意义,因为某些强制转换甚至不存在于字节码中,因为编译器将它们优化掉了。其他的用 checkcast 表示在字节码中。看这个例子:

package de.scrum_master.stackoverflow.q58984334;

public class Dummy {
public void foo() {
int i = (int) 42L;
System.out.println(i);
}

public void bar() {
Base base = new Sub();
Sub sub = (Sub) base;
System.out.println(sub);
}

static class Base {}
static class Sub extends Base {}
}

如果您通过 javap -c Dummy.class 拆卸它, 你得到:

Compiled from "Dummy.java"
public class de.scrum_master.stackoverflow.q58984334.Dummy {
public de.scrum_master.stackoverflow.q58984334.Dummy();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return

public void foo();
Code:
0: bipush 42
2: istore_1
3: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
6: iload_1
7: invokevirtual #21 // Method java/io/PrintStream.println:(I)V
10: return

public void bar();
Code:
0: new #30 // class de/scrum_master/stackoverflow/q58984334/Dummy$Sub
3: dup
4: invokespecial #32 // Method de/scrum_master/stackoverflow/q58984334/Dummy$Sub."<init>":()V
7: astore_1
8: aload_1
9: checkcast #30 // class de/scrum_master/stackoverflow/q58984334/Dummy$Sub
12: astore_2
13: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_2
17: invokevirtual #33 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
20: return
}

看?来自 long 的 Actor 阵容至 int即使需要在源代码中进行编译,也不存在。那么如何拦截呢?很抱歉这次深入探讨,实际答案在第一段中。

更新:
  • 鉴于您无法确定字节码中是否存在强制转换,您可以做的是编写一个简单的测试,扫描您的源代码并在每个 Maven 或 Gradle 构建期间编写报告。
  • 或者,如果您想变得更复杂,您可以编写一个编译器插件,该插件将检查表示已解析源代码的 AST(抽象语法树),然后在发现需要报告的内容时发出编译器警告。
  • 使用 AspectJ(不是 Spring AOP),您可以拦截对 Hibernate.unproxy() 的调用。 ,但是您需要检测的是没有这些调用,因此您无法为甚至不存在的东西编写切入点。
  • 关于java - AOP 检测 Hibernate.unproxy() 的所有类转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58984334/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com