代理模式的作用是:爲其他對象提供一種代理以控制對這個對象的訪問。
在某些情況下,一個客戶不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
靜態代理
涉及到的對象
代理類 CustommerProxy ,授代理類 ICustommer,分別都要實現接口
關係圖如下
場景示例:
現假如我客戶Custommer類是由A程序員開發的,Custommer類中有一個dosometing方法。
現有程序員B,他是畢業生,剛過來,程序員A給他發了一個包,沒有源代碼,並跟小B說需要對這個方法進行優化,需要在調用dosometing之前先校驗該用戶是否登錄了。那麼問題來了,小B在不知道源代碼的情況下,如何進行代碼重構
由於小B比較優秀,很快就想到了代理模式,所以噹噹的就寫下了如下代碼
接口類,由於代理類和被代理類
package com.cmh.service;
public interface Custommer {
void dosomething();
}
被代理類的實現類
public class ICustommer implements Custommer{
@Override
public void dosomething() {
// TODO Auto-generated method stub
System.out.println("I have something");
}
}
代理類的實現類
public class CustommerProxy implements Custommer{
private ICustommer custommer;
public CustommerProxy(ICustommer custommer){
this.custommer = custommer;
}
@Override
public void dosomething() {
// TODO Auto-generated method stub
System.out.println("do something before");
custommer.dosomething();
System.out.println("do something after");
}
}
測試類
public static void main(String[] args) {
pack();
}
public static void pack(){
ICustommer cus = new ICustommer();
Custommer proxy = new CustommerProxy(cus);
proxy.dosomething();
}
小B覺得這個也太他媽簡單了,於是就屁顛屁顛的跟他老大小A說,so easy,準備聽聽他老大好好的誇他,他老大一看代碼,哎不錯哦,這小子是可塑之才,當場就跟他說,小夥子,不錯嘛,那我再考考你,假如現在項目出現了變動,就是說我不僅在Custommer 需要改這個邏輯,我在其他類也需要這個邏輯。那麼怎麼辦?
小B心理一陣低估,握草,你大爺,然後就屁顛屁顛的跑回去找相關的資料,突然一個字眼出現在了小B眼前,動態代理?
動態代理
動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不僅簡化了編程工作,而且提高了軟件系統的可擴展性,因爲Java 反射機制可以生成任意類型的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力。 原來是利用反射的機制來實現的,今天我們不討論反射,我們看JDK的動態代理的實現。
若想實現 動態代理,就必須實現InvocationHandler 接口,InvocationHandler 的參數詳解
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader: 一個ClassLoader對象,定義了由哪個ClassLoader對象來對生成的代理對象進行加載
interfaces: 一個Interface對象的數組,表示的是我將要給我需要代理的對象提供一組什麼接口,如果我提供了一組接口給它,那麼這個代理對象就宣稱實現了該接口(多態),這樣我就能調用這組接口中的方法了
h: 一個InvocationHandler對象,表示的是當我這個動態代理對象在調用方法的時候,會關聯到哪一個InvocationHandler對象上
小B給出的代碼:
接口和原先的實現類都沒變
package com.cmh.service;
public interface Custommer {
void dosomething();
void deletesomething();
}
實現類
package com.cmh.service;
public class ICustommer implements Custommer{
@Override
public void dosomething() {
// TODO Auto-generated method stub
System.out.println("I have something");
}
@Override
public void deletesomething() {
// TODO Auto-generated method stub
System.out.println("I have Delete something");
}
}
動態代理類
package com.cmh.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class FactoryProxy implements InvocationHandler{
private Object target;
public Object getInstance(Object target) {
this.target = target;
//取得代理對象
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object result=null;
System.out.println("before");
//執行方法
result=method.invoke(target, args);
System.out.println("after");
return result;
}
}
測試類
public static void pack2(){
FactoryProxy proxy = new FactoryProxy();
Custommer custommer =(Custommer) proxy.getInstance(new ICustommer());
custommer.dosomething();
custommer.deletesomething();
}
至此,動態類就差不多了,動態代理在spring AOP或者struts2 中的攔截器中用的比較多。