如何使用反射在运行时扩展一个类

8
想象一下,我有两个类A和B,B继承自A,如下所示:
class B extends A
{
  ....
}

但是在我的情况下,Class A是加密的,只能在运行时由我的ClassLoader加载(在编译时,A.class无法被识别为.class文件,因为它被加密了)。这意味着在编译时不存在Class A。

我的问题是:

  1. 如果一些方法覆盖了Class A中的方法,我应该如何编写Class B的代码?
  2. 我如何指定Class B在运行时继承Class A?
2个回答

8

使用反射是无法实现的。但是,您可以通过CGLIB和可能的javassist来实现。


3

您可以创建一个虚拟的 A 副本,其中包含您想要覆盖的所有方法,并编译和部署 B。

如果您直到运行时才知道要覆盖哪些方法,则需要使用编译器 API 生成代码,但是像 Objectweb 的 ASM 这样的库可能会更简单。我更喜欢 ASM,因为它可以轻松地生成代码来从模板生成您想要的内容。即,您不必自己编写所有代码。


嗨,我认为“您可以创建一个虚拟副本A,其中包含您要覆盖的所有方法,并编译和部署B”是一种简单且正确的方法。但有一个问题不清楚。 我们说,我们有类A,我在编译时创建一个虚拟副本类dummy_A,以便部署类B。然后在运行时,如何将类dummy_A的内容替换为类A的内容。我感觉这就像尽管我们在编译时创建了一个类,但它只是一个外壳。然后在运行时,我们动态地更改类。如何进行更改?谢谢。 - user733172
不,你需要在同一个包中创建一个名为“A”的类。它与你想要扩展的类具有相同的名称、包和方法。当你部署代码时,只需部署B(不要部署虚拟的“A”)。你的类加载器将加载真正的A和B。只要你使用的方法等都是相同的,它就可以正常工作。 - Peter Lawrey
嗨,彼得,我看到了...好的,这是一个很棒的。 - user733172
嗨Peter,我明白了...这是一个很棒的方法。感谢您的帮助。还有一个问题。我的实际情况是,我需要首先创建一个包含Class A的JAR文件作为第三方组件。然后我开发Class B(扩展Class A)作为开源。您的方法是基于部署.class文件的。但在我的实际情况中,Class B无法扩展Class A(在单独的JAR库中),因为Class A已加密。这就是为什么需要Class A的包装器。我这样做是为了保护Class A代码。有什么想法吗?感谢您进一步的帮助和建议。 - user733172
A 可能已经被加密,但必须解密后才能使用。这意味着在运行时它就像任何其他类一样,所以我不认为有问题。 - Peter Lawrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接