-
上午捉摸了一下java的动态proxy
2004-04-14
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://piginzoo.blogbus.com/logs/139822.html
上午捉摸了一下java的动态proxy
开始时候,这样写:
interface IOneClass{
.....
class OneClass implements IOneClass
.....
InvocationHandler handler = new MyInvocationHandler();
IOneClass one =
(IOneClass) Proxy.newProxyInstance(
OneClass.class.getClassLoader(),
new Class[] { IOneClass.class },
handler);
one.hello_public("xxx");一直纳闷,OneClass啥时候传入呢?
后来修改了,InvocationHandler handler = new MyInvocationHandler(new OneClass());
......class MyInvocationHandler implements InvocationHandler {
private IOneClass one;
public MyInvocationHandler(IOneClass theone){
one = theone;<--------这里传入了
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxyed class name:" + proxy.getClass().getName());
System.out.println("calling method:" + method.getName());
System.out.println("param:" + args[0]);
return method.invoke(one, args);
//<------这里使用的就是OneClass的实例
}
不过,感觉这样好像很牵强附会似的,不过这是我能把OneClass的实例唯一绑定上的地方
看来,还得化点时间学习一下
//-----------------------------------------------------
今天中午吃饭的时候,还跟七彩浪聊呢,动态代理是如何实现的呢?
我的观点是:一定是java虚拟机里面放了个映射表,你运行Proxy.newInstance时候就好像
注册一样,吧某个类如何被代理的信息放到映射表中,下次一调用某个类,虚拟机就到注册
表中一找,发现有代理,就先运行代理了,呵呵。
狼的观点是,一定是某个类被修改了字节码,他的行为就变了,后来我一想,这不就是aspectj
的静态编入呢。终于,下午花了点时间看了看 java.lang.reflect.Proxy的源代码,发现了一些有意思的东西;
getProxyClass()方法是proxy类的核心:
/*
* Find or create the proxy class cache for the class loader.
*/
Map cache;
synchronized (loaderToCache) {
cache = (Map) loaderToCache.get(loader);
if (cache == null) {
cache = new HashMap(3);
loaderToCache.put(loader, cache);
}
/*
* This mapping will remain valid for the duration of this
* method, without further synchronization, because the mapping
* will only be removed if the class loader becomes unreachable.
*/
}/*
* Look up the list of interfaces in the proxy class cache using
* the string key. This lookup will result in one of three possible
* kinds of values:
* null, if there is currently no proxy class for the list of
* interfaces in the class loader,
* the pendingGenerationMarker object, if a proxy class for the
* list of interfaces is currently being generated,
* or a weak reference to a Class object, if a proxy class for
* the list of interfaces has already been generated.
*/
synchronized (cache) {
/*
* Note that we need not worry about reaping the cache for
* entries with cleared weak references because if a proxy class
* has been garbage collected, its class loader will have been
* garbage collected as well, so the entire cache will be reaped
* from the loaderToCache map.
*/
do {
Object value = cache.get(key);
if (value instanceof Reference) {
proxyClass = (Class) ((Reference) value).get();
}
if (proxyClass != null) {
// proxy class already generated: return it
return proxyClass;你看,果然是有各cache,存放这些代理类。
那么,如果没有,代理类如何产生呢,别着急,答案就在下面
/*
* Verify that the class loader hasn't already
* defined a class with the chosen name.
*//*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
try {
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);看到了吧,ProxyGenerator.generateProxyClass()
动态产生一个类定义,然后还原成一个类(Class)。
另外,InvokeHandler是通过构造函数传入动态代理类的,这点从
Porxy.newProxyInstance()的方法就可以看出:
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}Class cl = getProxyClass(loader, interfaces);
try {
Constructor cons = cl.getConstructor(constructorParams);
return (Object) cons.newInstance(new Object[] { h });
<-------h就是InvocationHandler的实例总之,对于动态代理,确实给我们提供了一个很好的机制,
来改变一个类的一些行为,不过,有一点不爽,就是,
被代理的类必须先得有一个interface才行。回头看看nanning和cglib如何解决的这个问题吧。
收藏到:Del.icio.us







