我正在使用CGLib来代理类。我遇到了一个问题,我无法增强匿名类,因为它们没有默认的构造函数。
我的代码如下所示:
Enhancer enhancer = new Enhancer();
enhancer.setCallback(new MethodInterceptor() { .... });
enhancer.setSuperclass(type); // type is the Class I'm trying to enhance
enhancer.create();但是,如果增强类是匿名的(没有默认构造函数),则会引发以下异常。
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given有办法绕过这件事吗?
发布于 2014-07-25 21:35:02
JVM的验证器确保您调用有效的构造函数链。唯一的解决办法是在启动JVM时通过命令行禁用验证器,这是您通常不想做的事情,因为它给您的应用程序带来了一些不安全性。
因此,您必须调用匿名类的有效构造函数,该构造函数由cglib创建的子类模拟。因此,该类的构造函数以其封闭类的实例作为其参数。如果您使用cglib创建一个从未调用真正方法的纯代理,您可以考虑将null交给这个构造函数,但在传递参数之前仍然需要选择正确的构造函数。
您可以通过调用:
enhancer.create(new Class<?>[] {type.getEnclosingClass()}, new Object[] {null})其中,上面的调用选择正确的构造函数并使用null值初始化匿名类的外部实例字段。
或者,您可以使用内部OpenJDK类ReflectionFactory来创建实例,而无需调用任何构造函数。在调用enhancer.createClass()之后,这是可能的。但是,这需要额外的准备,因为您需要指定不同的回调。
但是,您可能只想把cglib放在一起。作为一个免责声明,我是另一个库的作者,我想推荐给你。使用字节巴迪,您在创建类方面有更多的自由,使用它来定义您的逻辑更容易。使用Buddy,你可以写
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();实现同样的逻辑。只需删除调用侦听所不需要的(带注释的)参数。
https://stackoverflow.com/questions/24951944
复制相似问题