Java实现动态代理

在看AOP(Aspect Oriented Programming)的时候,看到有人说利用Java的动态代理可以轻松实现,于是准备对这个动态代理一探究竟...
首先google了一把,发现关于动态代理的material的确很多,先找了两篇中文的看了一下,大概明白了怎么回事,感觉很简单的一点东西,虽然有些细节还不是太清楚,溯本归源,到sun公司网站去看,然后通过自己动手做了个sample,终于搞清楚了它的来龙去脉,在这里与大家分享一下,如有不正之处,敬请指正...
首先简单回顾一下代理模式的内容,“动态”毕竟只是个修饰词:)...
定义(GoF):为其他对象提供一种代理以控制对这个对象的访问,那么简单分析一下这个定义的含义:

1、区分代理对象和被代理对象,客户直接跟代理对象交互,即代理对象向用户隐藏了被代理对象

2、代理对象并不代替被代理对象的工作,真正的工作还是由被代理对象做,但可以通过代理对象增加一些额外的功能(对用户而言)

有了上面的基础,让我们看一下Java中的动态代理又是怎么一回事...
首先,这个动态的含义,我觉着很多文章上并没有明确指出,很多文章只是给出了个例子,但并没有解释清楚,我在这里给大家深入介绍一下,希望是对其他文章的一个补充...
其实,这里动态的含义,是指动态生成代理类,注意是生成类,而不是对象,这利用到了动态代码生成,而且这个动态生成的代理类宣称实现了被代理类的所有接口,那么这是如何做的呢?这是因为我们在调用Proxy.newInstance(...)的时候,第二个参数就将被代理类的接口传给了该函数用于动态生成代理类,当然上面这个函数最终返回的是一个代理类的实例,但我们需要知道这个函数内部实际上是先调用Proxy.getProxyClass()生成代理类,然后才由该代理类生成代理对象的。

Ok,我们清楚了代理类及其实例的生成过程,那么我们下面看看代理类是如何调用被代理类中的对应方法的呢?其实,[color=darkred]动态生成的代理类并没有直接调用被代理类的对应方法,而是调用了在生成代理类时穿过去的一个InvocationHanlder接口的一个实现。也就是说在动态生成的代理类中,它将方法调用全部委托给了InvocationHanlder,它调用了InvocationHanlder的invoke函数,而在invoke函数中,InvocationHanlder又通过反射调用了被代理类的对应函数,这样一个好处是我们可以自己定制代理类如何调用被代理类的方法,比如我们可以在调用被代理类的方法之前和之后加入log功能等。
但注意,Java的动态代理只针对接口。[/color]写到这不知道讲清楚了没有,下面看个例子吧,可能就更容易理解了...
/*
* @(#)HelloWorld.java 1.82 99/03/18
*
* Copyright (c) 2006-2008 ics@nju.edu.cn
* Nanjing University
* All rights reserved.
*
* This software can be used freely, however, a comment about where it
* is from is necessary when you use it in your code.
*/
package example.dynamicproxy;
/**
* @name HelloWorld.
*
* @version 1.00 18 Mar 1999
* @author Lin Qiang
*/
public interface HelloWorld {
void sayHello(String what);
}

///
/*
* @(#)HelloWorldImpl.java 1.82 99/03/18
*
* Copyright (c) 2006-2008 ics@nju.edu.cn
* Nanjing University
* All rights reserved.
*
* This software can be used freely, however, a comment about where it
* is from is necessary when you use it in your code.
*/
package example.dynamicproxy;
/**
* @name HelloWorldImpt.
*
* @version 1.00 18 Mar 1999
* @author Lin Qiang
*/
public class HelloWorldImpl implements HelloWorld {
public void sayHello(String what) {
System.out.println(what);
}
}
///

/*
* @(#)HelloProxy.java 1.82 99/03/18
*
* Copyright (c) 2006-2008 ics@nju.edu.cn
* Nanjing University
* All rights reserved.
*
* This software can be used freely, however, a comment about where it
* is from is necessary when you use it in your code.
*/
package example.dynamicproxy.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import example.dynamicproxy.HelloWorld;
import example.dynamicproxy.HelloWorldImpl;
import example.dynamicproxy.UseProxy;
/**
* @name HelloProxy.
*
* @version 1.00 18 Mar 1999
* @author Lin Qiang
*/
public class HelloProxy implements InvocationHandler {
private Object obj;

public HelloProxy(Object obj2) {
this.obj = obj2;
}

public static Object newInstance(Object obj2)
{
return Proxy.newProxyInstance(obj2.getClass().getClassLoader(),
obj2.getClass().getInterfaces(),
new HelloProxy(obj2));
}
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
Object result = null;
System.out.println("Entering function: " + arg1.getName() + "...");
result = arg1.invoke(obj, arg2);
System.out.println("Leaving function: " + arg1.getName() + "...");
return null;
}
public static void main(String[] args)
{
HelloWorld he = (HelloWorld)HelloProxy.newInstance(new HelloWorldImpl());
he.sayHello("hello,moto");
}
}
<End>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值