我怎样才能创建final类动态代理?(How can I create dynamic proxy

2019-09-02 05:13发布

总之:1.我有,我想为它创建动态代理一些最后一类。 我该怎么做? 2.我可以转换MethodHandle的方法?

所有的细节首先,不存在任何的API来MethodHandle转换的方法? 喜欢的东西在java.lang.invoke.MethodHandles

public MethodHandle unreflect(Method m) throws IllegalAccessException;

但相反的方式arrond?

让说,我想创建动态的java.lang.reflect.Method。 据defiend为

public final
   class Method extends AccessibleObject implements GenericDeclaration,
                                                 Member ;

所以,如果我想使用JDK动态代理,我必须使用一些接口(例如会员)。 虽然有2个主要drawabacks。 首先,方法如

public Class<?>[] getParameterTypes();

而如

public Class<?> getReturnType();

没有任何接口的一部分,而它们被广泛使用。

第二个缺点是,它不能提供简易替换。 也就是说,我无法将动态代理传递给需要java.lang.reflect.Method中的代码。

另一种方法是使用CGLIB或Javaassist。 据我所知,CGLIB不能代理final类,是吗? 可以Javaassist代理final类? 我怎样才能“删除”,从最后的类标识符? AFAIL,Javvassist能以某种方式做到这一点...

Answer 1:

这取决于你需要什么样的代理权。 基本上有三种aproaches的你如何能做到这一点,其中两个是在生产代码中是可行的。 作为@probrekely指出,CGLIB或Javassist是IST他们动态创建一个子类,什么是不可能的最后类的问题。 您可以通过避免这种情况:

  • 禁用字节码验证。 Java运行时验证以确保没有恶意字节代码加载字节码。 当例如接收类通过网络或互联网,例如小应用程序,这是很重要的。 通过这种方式,你可以创建一个最终类的子类,因为字节码验证就不会阻止你。 可以想像,如果你只运行受信任的代码可以禁用此验证。 这可以通过运行来完成:

     java -Xverify:none ApplicationName 

    然而,这是解决方案,我建议你最少。 我不会用这个形式给出了生产代码,但它肯定是最容易实现的解决方案。

  • 取出final之前或类被加载之后,从装入的类改性剂,。 这可以通过使用实现Java代理 。 一个Java剂可以在通过经由命令行或在运行时应用程序启动时被安装附加API 。 有了这样ASM字节码工具,你可以解析的原始字节数组和相关的所有类别中删除final修饰符。 也可以重新定义已经装载的类。 删除final修改并没有引进与旧版本的类这样的冲突,这样的重新定义始终是可能的。

  • 有一样我删除所描述的final修改,但重新加载的类实际上包含原始类中所有的设备逻辑。 这aporach将最certanly需要最大的努力,但是这会让你的仪表透明单位所有其他代码。 这将是所有解决方案的干净的解决方案。



Answer 2:

对不起,你想要什么是不可能的:

您可以使用CGLIB或Javassist是创建具体类的代理,因为这些库动态生成你想代理类的子类。 一个final类不能被继承,所以你不能创建一个代理这种方式。

PowerMock不会让你代理final的类和方法,但这是因为它运行其特殊下进行测试ClassLoader ,它使用了Javassist修改,因为他们正在被装入要代理的类的字节码。 (你不会想用这种生产的事情,因为一般修改后的“僵尸”之类的版本,结果将不利于比运行特定的模拟单元测试什么其他东西。)

该PowerMock方法不会在这里工作,但是-你希望代理java.lang.reflect.Method ,这是在引导类路径,所以将任何PowerMock / Javassist进行类工具之前加载,因此不被代理的。



文章来源: How can I create dynamic proxy for final Class?