动态代理,首先得说说我对"代理"这个词的理解,比如A能做某件事,但我用B来通知A去做,那就达到了代理的作用,我不需要去亲自请A来做,只要有B就行,B就是A的代理。
站在编程的角度讲,其实上面的说法应该属于静态代理,因为我事先知道是A、B,也就是我要创造出B才能让B去执行代理。
但如果有很多代理呢,换句话说,我根本不知道能做某件事的那个人名字叫什么,那就只能通过“动态代理'来帮我们解决问题了。
这里借用从网上看到的一句关于动态代理的话——“在程序运行时,运用反射机制动态创建而成”
没错,我觉得之所以称之为“动态“, 就是因为有了”反射“这个利器, 运用java的反射可以实现很多东西, 而且理解动态代理,
就需要首先掌握怎么运用反射来调用某个类的某个方法。
下面我们先用代码来看看怎么用java的反射实时调用某个类的某个方法。
Class<?> xx = Class.forName("x");
Method method = xx.getMethod("xxx");
method.invoke(xx.newInstance());
这样,我们就利用反射调用了x类的xxx方法。
这里要注意的是,我们调用的这个xxx方法是无参数的。
假如x类有另外一个方法publci void xxxx(String x, int y), 我们就通过如下代码来调用
Class<?> xx = Class.forName("x");
Method method = xx.getMethod("xxxx", String.class, int.class);
method.invoke(xx.newInstance(),"hello",20);
这是理解动态代理之前我们现需要掌握的反射基础。
下面我们开始写个能体现动态代理的例子
1.首先我们有个接口
interface testInterface{
public String say(String something,int num);
}
public class testImplement implements testInterface {
@Override
public String say(String something, int num) {
return something+" "+num;
}
}
3.我们需要写一个类实现InvocationHandler接口
public class MyInvocationHandler implements InvocationHandler {
private Object obj = null;
public Object bind(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
//做自己的事情
System.out.println("预先处理");
//接口自己的处理
Object obj = arg1.invoke(this.obj, arg2);
return obj;
}
}
4.编写测试类运行看看
public class helloTest {
public static void main(String[] args){
MyInvocationHandler demo = new MyInvocationHandler();
testInterface t = (testInterface)demo.bind(new testImplement());
String info = t.say("hello,world", 21);
System.out.println(info);
}
}
运行结果:
预先处理
hello,world 21
发现了么?
我们在原先接口的say方法前加入我们自己的预处理,但我们并不需要去改变testInterface接口的任何代码。
而且, 无论是什么类我们都可以在执行这个它之前加入我们的预处理代码,程序运行时利用java的反射机制可以动态的实例化对象。
这种思想在很多框架中我们都可以看到,例如spring。
动态代理真的是体现了java的编程之美。