如果把要被代理的對象比喻成演員,那代理對象就是它的經紀人。
經紀人會幫助演員處理很多事情,體現在代碼裏就是各種各樣的方法。
所以說代理對象方便了被代理對象的日後維護和修改,降低了程序的耦合性,提高了程序的魯棒性。
功能介紹完了,我們來看一下具體的實例:
要實現動態代理,要實現兩個重要的類,一個是Proxy——生成代理對象的類,一個是 InvocationHandler——處理被代理對象的類,可以進行自定義。
首先來看一下實現動態代理的格式:
Proxy.newProxyInstance(loader, interfaces, h);
Proxy——用來生成代理對象
newProxyInstance(...)——創建一個Proxy實例
loader——當前類的類加載器
interfaces——被代理對象的所有接口
h——InvocationHandler處理類的實現
從格式上可以看出來,實現動態代理要獲取當前類的類加載器,在哪個類中就獲取哪個類的加載器即可,還要獲取被代理對象的所有接口。
下面通過實例來看一下動態代理的用法:
package cn.itcast_動態代理;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) {
//list是被代理的對象
final ArrayList list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
System.out.println(list);
ArrayList list2 = new ArrayList();
list.add("xx");
List p = (List)Proxy.newProxyInstance(Demo.class.getClassLoader(), list.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//System.out.println(proxy.getClass());
//增強add方法
String name = method.getName();
//System.out.println(name);
if("add".equals(name))
{
System.out.println("進行添加操作:");
list.add("***");
return true;
}
if("size".equals(name))
{
return 0;
}
if("remove".equals(name))
{
throw new UnsupportedOperationException();
}
return method.invoke(list, args);
}
});
//代理對象p中與add方法名相同的方法,並非list中原來的add方法,所以結果會返回false
boolean b = p.add("123");
System.out.println("添加成功?"+b);
//同理此size方法也是p中的與size同名的方法
int n = p.size();
System.out.println("該集合中一共有:"+n+"個元素");
//輸出list後,發現list中並非沒有元素,而是有四個元素
System.out.println(list);
//addAll方法因爲沒有在p中進行判斷,所以沒有影響
p.addAll(list2);
//這裏也是p中經過判斷的remove方法
boolean re = p.remove("aaa");
System.out.println("移除成功?"+re);
}
}
此處我們把創建的list對象當做被代理對象,按照上面的格式創建Proxy實例後,在InvocationHandler處理類中重寫invoke方法,獲取list對象的方法名後list對象中的方法就任我們擺佈了,在進行判斷並對list中的add、size、remove方法進行操作後,我們試着調用一下p對象的add、size和remove方法,控制檯會出現這樣的結果:
其中,add、size、remove方法的都是按照p對象中判斷後的同名方法執行的,而沒有進行判斷的靜態方法addAll還是按照list對象中的原來的功能執行,由此可見,動態代理可以修改被代理對象中的方法,從而降低了程序的耦合性,提高了程序的可維護性。