具有匿名类的CGLib Enhancer [英] CGLib Enhancer with anonymous class
问题描述
我正在使用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屋!