Java 尝试更改CGLib代理字段值时出现异常
我创建了一个类的CGLib动态代理,但是当我试图访问原始类中声明的任何字段时,我获得了java.lang.NoSuchFieldException。我需要获取字段以更改其值 顺便说一下,这是代理所基于的类:Java 尝试更改CGLib代理字段值时出现异常,java,proxy,cglib,Java,Proxy,Cglib,我创建了一个类的CGLib动态代理,但是当我试图访问原始类中声明的任何字段时,我获得了java.lang.NoSuchFieldException。我需要获取字段以更改其值 顺便说一下,这是代理所基于的类: public class Person { private String name; .... public String getName() { return name; } public void setName(String
public class Person {
private String name;
....
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
...
}
这是引发上述异常的代码片段(在“MethodInterceptor”的“intercept”方法中)(更具体地说是第一行):
您知道访问所需字段或更改其值的其他方法吗
谢谢。试试:
Field field = instance.getClass().getDeclaredField("name");
如中所述,仅适用于公共字段,但适用于整个类层次结构。您可以将其视为检查类的公共接口。适用于私有字段,不会检查类层次结构;您可以将其视为解决类的实现。尝试:
Field field = instance.getClass().getDeclaredField("name");
如中所述,仅适用于公共字段,但适用于整个类层次结构。您可以将其视为检查类的公共接口。适用于私有字段,不会检查类层次结构;您可以将其视为解决类的实现。显然,CGLib代理是原始类的子类。因此,以下代码运行良好:
Field field = instance.getClass().getSuperclass().getDeclaredField("name");
显然,CGLib代理是原始类的一个子类。因此,以下代码运行良好:
Field field = instance.getClass().getSuperclass().getDeclaredField("name");
尽管您已经找到了解决问题的方法,但以下是cglib的工作原理以及导致问题的原因的简短说明。考虑到您的
Person
类,cglib在运行时创建了另一个代表您的代理的类。这个类在Java源代码中大致如下所示,但是,使用的许多实例都是缓存的,这就是cglib添加其他几个字段的原因。此外,通过使用不同的静态字段注入MethodInterceptor
:
public class Person$EnhancedByCglib extends Person {
private static class GetNameMethodProxy extends MethodProxy {
@Override
public Object invokeSuper(Object instance,
Object[] arguments) {
return ((Person$EnhancedByCglib) instance).getNameSuper();
}
// ...
}
// ...
private static MethodInterceptor methodInterceptor;
@Override
public String getName() {
return (String) methodInterceptor.intercept(this,
getClass().getDeclaredMethod("getName"),
new Object[0],
new GetNameMethodProxy());
}
private String getNameSuper() {
return super.getName();
}
@Override
public void setName(String name) {
methodInterceptor.intercept(this,
getClass().getDeclaredMethod("setName", String.class),
new Object[] {name},
new SetNameMethodProxy());
}
private void setNameSuper(String name) {
super.setName(name);
}
// ...
}
如您所见,拦截是通过覆盖任何方法实现的。这样,您的MethodInterceptor
将被调用,而不是使用MethodProxy
仍然可以调用的原始方法。由于拦截,在使用cglib时,调用getMethod
或getDeclaredMethod
可以正常工作。但是,字段不是继承的,这就是为什么需要向上浏览一个类的类层次结构。这就是为什么:
instance.getClass().getSuperclass().getDeclaredField("name");
工作。请注意,不再维护cglib。看看我的图书馆,以防你正在寻找替代品。但是请注意,我将在下周发布一个完全稳定的版本。当前的v0.1版本包含一些不成熟的功能。尽管您已经找到了解决问题的方法,但下面简要说明了cglib的工作原理以及导致问题的原因。考虑到您的
Person
类,cglib在运行时创建了另一个代表您的代理的类。这个类在Java源代码中大致如下所示,但是,使用的许多实例都是缓存的,这就是cglib添加其他几个字段的原因。此外,通过使用不同的静态字段注入MethodInterceptor
:
public class Person$EnhancedByCglib extends Person {
private static class GetNameMethodProxy extends MethodProxy {
@Override
public Object invokeSuper(Object instance,
Object[] arguments) {
return ((Person$EnhancedByCglib) instance).getNameSuper();
}
// ...
}
// ...
private static MethodInterceptor methodInterceptor;
@Override
public String getName() {
return (String) methodInterceptor.intercept(this,
getClass().getDeclaredMethod("getName"),
new Object[0],
new GetNameMethodProxy());
}
private String getNameSuper() {
return super.getName();
}
@Override
public void setName(String name) {
methodInterceptor.intercept(this,
getClass().getDeclaredMethod("setName", String.class),
new Object[] {name},
new SetNameMethodProxy());
}
private void setNameSuper(String name) {
super.setName(name);
}
// ...
}
如您所见,拦截是通过覆盖任何方法实现的。这样,您的MethodInterceptor
将被调用,而不是使用MethodProxy
仍然可以调用的原始方法。由于拦截,在使用cglib时,调用getMethod
或getDeclaredMethod
可以正常工作。但是,字段不是继承的,这就是为什么需要向上浏览一个类的类层次结构。这就是为什么:
instance.getClass().getSuperclass().getDeclaredField("name");
工作。请注意,不再维护cglib。看看我的图书馆,以防你正在寻找替代品。但是请注意,我将在下周发布一个完全稳定的版本。当前的v0.1版本包含一些不成熟的功能。感谢您的提示。我按照您的建议更改为“getDeclaredField”,并获得了与CGLib相关的各种字段。但是问题仍然存在,因为返回的字段中没有一个是“name”字段。谢谢您的提示。我按照您的建议更改为“getDeclaredField”,并获得了与CGLib相关的各种字段。但是,问题仍然存在,因为返回的字段中没有一个是“name”字段。