论坛首页 Java企业应用论坛

java动态代理之一:java Proxy实现

浏览 3169 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-03-26  
动态代理类是一个实现在创建类时在运行时指定的接口列表的类。

InvocationHandler handler = new MyInvocationHandler(...);
     Class proxyClass = Proxy.getProxyClass(
         Foo.class.getClassLoader(), new Class[] { Foo.class });
     Foo f = (Foo) proxyClass.
         getConstructor(new Class[] { InvocationHandler.class }).
         newInstance(new Object[] { handler });

proxyClass 是一份动态生成的字节码,在创建时需指定一个加载器 Foo.class.getClassLoader()(在此可理解为:给他指定一个妈妈),给它一个接口对象数组,即该代理类实现了哪些接口。
调用 Class proxyClass = Proxy.getProxyClass(
         Foo.class.getClassLoader(), new Class[] { Foo.class });
即生成了一个动态字节码。通过反射查看它的构造函数,发现它的构造函数需要传递一个InvocationHandler 对象。 其实在生成的动态字节码实现接口的方法中,都是调用了InvocationHandler 对象的invoke方法。
在这里我们可以大概想象生成的动态字节码的内部结构:
public classs Xxx$Proxy{
private InvocationHandler  invocationHandler ;
public Xxx$Proxy(InvocationHandler  invocationHandler  ){
this.invocationHandler =invocationHandler ;
}
Method1(Object[] args){
invocationHandler.invoke(this,...);
}
Method2(Object[] args){
invocationHandler.invoke(this,...);
}

}


引用
我们在看InvocationHandler 接口,其内部就一个方法
Object invoke(Object proxy,
              Method method,
              Object[] args)
              throws Throwable

需要一个代理对象,方法对象,方法参数。

通常我们在InvocationHandler实现类中,放入真实的角色和Advice(增强功能类)。
在通过反射执行method对象的Invoke方法时,传入真实对象。

上面代理实现是通过分部执行,Proxy类的newProxyInstance(Foo.class.getClassLoader(),
                                          new Class[] { Foo.class },
                                          handler);

方法可以一次生成该代理对象,由以上的解释,我们不难想象需要三个参数。即给它个妈妈(加载器),实现了那些接口(接口数组),InvocationHandler对象。

下面是一个动态代理工厂:


public class ProxyFactoryBean {

	private Advice advice;
	private Object target;
	
	public Advice getAdvice() {
		return advice;
	}

	public void setAdvice(Advice advice) {
		this.advice = advice;
	}

	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}

	public Object getProxy() {
		Object proxy = Proxy.newProxyInstance(
				target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler(){
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						advice.beforeMethod(method);
						Object retVal = method.invoke(target, args);
						advice.afterMethod(method);
						return retVal;						
						
					}
				}
				);
		return proxy;
	}



我们可以动态的指定一个代理目标target,和增强功能对象advice。使用getProxy即会生成一个动态代理对象。

该种代理方式,代理的对象必须是实现了某个接口。
   发表时间:2011-03-29  
写的很好  看明白了点InvocationHandler的作用,但是对Invoke函数还是有点迷茫 ,下面是《java编程思想》里面的代码:

public class DynamicProxyHandler implements InvocationHandler {
private Object proxied;

public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("**** proxy: " + proxy.getClass() + ",method: "
+ method + ",args: " + args);
if (args != null)
for (Object arg : args)
System.out.println(" " + arg);
return method.invoke(proxied, args);
}
}
对于这里的DynamicProxyHandler中传入的proxied参数,我发现只是把它赋值到这个函数中,并没有在第一个invoke函数中调用 ,就在return中返回了。。还有就是在第一个invoke函数中第一个参数proxy不明白是什么作用
0 请登录后投票
   发表时间:2011-03-30  
Method.invoke 就调用的是要代理的对象proxied的方法
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics