具有匿名类的CGLib Enhancer [英] CGLib Enhancer with anonymous class

查看:154
本文介绍了具有匿名类的CGLib Enhancer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用CGLib代理类。我遇到了一个无法增强匿名类的问题,因为它们没有默认构造函数。

I'm using CGLib to proxy classes. I've hit a problem where I can not enhance anonymous classes because they don't have a default constructor.

我的代码如下所示:

Enhancer enhancer = new Enhancer();
enhancer.setCallback(new MethodInterceptor() { .... });
enhancer.setSuperclass(type); // type is the Class I'm trying to enhance
enhancer.create();

但是,如果增强类是匿名的(没有默认构造函数),则抛出以下异常。

However this throws the following exception if the enhanced class is anonymous (no default constructor).

java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given

有没有办法解决这个问题?

Is there a way to go around this?

推荐答案

JVM的验证程序确保您调用有效的构造函数链。解决这个问题的唯一方法是在启动JVM时通过命令行禁用验证程序,这通常不是你想要做的,因为它会给你的应用程序带来一些不安全感。

A JVM's verifier assures that you call a valid constructor chain. The only way around this is to disable the verifier by command line when starting up the JVM and this is nothing you generally want to do as it introduces several insecurities to your application.

因此,您必须调用匿名类的有效构造函数,该构造函数由 cglib 创建的子类模仿。因此,该类的构造函数将其封闭类的实例作为其参数。如果您使用 cglib 创建一个从不调用真实方法的纯代理,您可以考虑将 null 交给此构造函数但你仍然需要在处理参数之前选择正确的构造函数。

Thus, you will have to call a valid constructor of your anonymous class which is imitated by the subclass that is created by cglib. This class's constructor thus takes an instance of its enclosing class as its argument. If you use cglib to create a pure proxy that never calls a real method, you can consider handing null to this constructor but you still need to select the right constructor before handing the argument.

你可以通过调用来实现这个目的:

You can achieve this by calling:

enhancer.create(new Class<?>[] {type.getEnclosingClass()}, new Object[] {null})

上面的调用选择了正确的构造函数,并用 null 初始化匿名类的外部实例字段值。

where the above call selects the correct constructor and initializes the anonymous class's outer instance field with a null value.

或者,您可以使用内部OpenJDK类 ReflectionFactory 来创建实例而不调用任何构造函数。在调用 enhancer.createClass()之后,这是可能的。这需要额外的准备,因为您需要指定不同的回调。

Alternatively, you could use the internal OpenJDK class ReflectionFactory in order to create an instance without calling any constructor. This is possible after calling enhancer.createClass(). This requires however additional preparation as you need to specify a different callback.

但是,您可能只想完全删除 cglib 。作为免责声明,我是我想向您推荐的替代图书馆的作者。使用 Byte Buddy ,您可以更自由地创建类,并且使用它更容易定义逻辑。使用Byte Buddy,你可以写

However, you might just want to drop cglib alltogether. As a disclaimer, I am the author of an alternative library I want to recommend to you. Using Byte Buddy, you have more freedom in creating classes and it is easier to define your logic using it. Using Byte Buddy, you can write

new ByteBuddy()
  .subclass(type)
  .method(any()).intercept(MethodDelegation.to(new Object() {
     @RuntimeType
     public Object intercept(@SuperCall Callable<?> c, 
                             @Origin Method m, 
                             @AllArguments Object[] a) throws Exception {
       // implement your interception logic
     }
   }).make();

并实现相同的逻辑。只需删除调用截取所不需要的(带注释的)参数。

and achieve the same logic. Simply remove the (annotated) arguments you do not need for calling your interception.

这篇关于具有匿名类的CGLib Enhancer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆