【发布时间】:2015-11-18 09:36:57
【问题描述】:
我正在尝试使用以下代码为 java.net.SocketImpl 类创建 CGLib 代理:
Enhancer e = new Enhancer();
e.setSuperclass(SocketImpl.class);
e.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object socketImplInstance, Method method, Object[] arguments, MethodProxy methodProxy) throws Throwable {
System.out.println("Got call to " + method.getName());
return methodProxy.invokeSuper(socketImplInstance, arguments);
}
});
SocketImpl socketImpl = (SocketImpl)e.create();
Method m = SocketImpl.class.getDeclaredMethod("getSocket");
m.setAccessible(true);
System.out.println("getSocket: " + m.invoke(socketImpl));
m = SocketImpl.class.getDeclaredMethod("getLocalPort");
m.setAccessible(true);
System.out.println("getLocalPort: " + m.invoke(socketImpl));
由于这段代码,我得到了一个输出:
getSocket: null
Got call to getLocalPort
getLocalPort: 0
我们没有“Got call to getSocket”,所以 SocketImpl#getSocket() 没有被拦截。此方法与 SocketImpl#getLocalPort() 的不同之处仅在于访问级别 - SocketImpl#getLocalPort() 是受保护的,而 SocketImpl#getSocket() 是包私有的。我与其他包私有方法 SocketImpl#getServerSocket() 有相同的行为。
我尝试使用用户类(根据 SocketImpl 是抽象的)重现此错误,但如果我们有,一切都按预期工作:
package userpackage;
public abstract class Abstract {
void testMethod() {}
}
package somethingother;
Enhancer e = new Enhancer();
e.setSuperclass(Abstract.class);
e.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object abstractInstance, Method method, Object[] arguments, MethodProxy methodProxy) throws Throwable {
System.out.println("Got call to " + method.getName());
return methodProxy.invokeSuper(abstractInstance, arguments);
}
});
Abstract abstrct = (Abstract)e.create();
Method m = Abstract.class.getDeclaredMethod("testMethod");
m.setAccessible(true);
System.out.println("testMethod: " + m.invoke(abstrct));
我们得到输出:
Got call to testMethod
testMethod: null
没关系,这个包私有方法被拦截了。
请您帮我理解一下这个例子发生了什么以及为什么我们有不同的行为。我只有一个猜测,它可能与 SecurityManager 有关,但在那种情况下,你能指出它为什么不起作用的具体情况吗?
我使用 CGLib 3.1 和 3.2.0 进行测试。
【问题讨论】: