什么是代理
這里的代理可以聯(lián)系生活中的代理,就是代表某些人或事物做一些事情,舉幾個例子:1.中介就是一個典型的代理,你把房子掛到中介,中介就會幫你把房子的標價報給想買房的人;2.你打官司的時候,花錢請了律師,律師就會幫你打官司,替你說話..等等現(xiàn)實中有很多代理的例子。
為什么使用代理
還是引用上面的例子,你之所以把房子掛到中介,是因為你很忙,沒時間處理,而且中介可以聯(lián)系更多的買家;請律師,是因為律師懂得更多的法律知識,相當于對你進行了武裝。
軟件應用中的代理
經(jīng)過上面對現(xiàn)實生活中代理的簡單介紹,下面說一下我們編寫軟件應用中代理模式的使用。
在軟件應用中,代理模式的使用有三種情況:靜態(tài)代理,JDK動態(tài)代理),cglib動態(tài)代理;下面進行分別的介紹。
- 靜態(tài)代理
靜態(tài)代理是指被代理類和代理類都實現(xiàn)同一個接口,對于被代理類的方法訪問需要通過代理類調用- 靜態(tài)代理的缺點:
1、代理的職能單一,在代碼中需要寫多個代理來完成不同的功能
2、在編譯器已經(jīng)確定對被代理類的方法的調用,不適合做更多的擴展
示例代碼:
首先是公用接口
/**
* Created by bitsino-001 on 2019/5/17.
* 通過房子中介演示靜態(tài)代理
* 這是個買房者和中介的公用接口
*/
public interface SellHouse {
void price_house();
}
被代理類實現(xiàn)公用接口,這里就是賣房子的人
/**
* Created by bitsino-001 on 2019/5/17.
* 實際賣方的人(被代理類)
*/
public class Seller implements SellHouse {
@Override
public void price_house() {
System.out.println("我是房主,萬科洋房,110平,售價150萬!");
}
}
接下來是代理類也實現(xiàn)公用接口,這里就是房屋中介
/**
* Created by bitsino-001 on 2019/5/17.
* 中介代理類
*/
public class Zhongjie implements SellHouse {
//
Seller seller = new Seller();
@Override
public void price_house() {
System.out.println("我是房屋中介,房主急售!");
seller.price_house();
}
}
下面是測試代碼
/**
* Created by bitsino-001 on 2019/5/17.
*/
public class TestProxy {
public static void main(String[] args) {
SellHouse sellHouse = new Zhongjie();
sellHouse.price_house();
}
}
輸出結果:通過代理類調用了被代理類的方法,同時,也可以看做代理類對被代理類做了宣傳,也可以叫做增強,這個概念在后面的學習中會看到,如果學習了spring ,對AOP有了解那么這個概念應該熟悉。

圖片.png
- JDK動態(tài)代理
JDK動態(tài)代理和靜態(tài)代理類似,需要實現(xiàn)公共的接口,但是彌補了上面說的靜態(tài)代理的缺點。動態(tài)代理是在運行時動態(tài)的為被代理類創(chuàng)建代理對象,公用接口中的方法都被轉移到調用處理器一個集中的方法中執(zhí)行,可以更加靈活的處理多個方法的調用執(zhí)行。
示例代碼:
package dynamic_proxy;
/**
* Created by bitsino-001 on 2019/5/17.
* 一個普通的用戶,需要請律師代理他打官司
*/
public class User implements DaGuanSi {
@Override
public void juzheng() {
System.out.println("用戶請律師幫忙舉證");
}
@Override
public void susong() {
System.out.println("用戶請律師幫忙訴訟");
}
}
package dynamic_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by bitsino-001 on 2019/5/17.
* 演示如何實現(xiàn)動態(tài)代理
*
*/
public class TestDynamicProxy {
public static void main(String[] args) {
//獲得代理類,需要用到JDK中的 Proxy.newProxyInstance()方法
// 在Proxy.newProxyInstance()中需要傳入三個參數(shù)
/* public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
* 第一個是被代理類的類加載器,第二個是被代理類實現(xiàn)的接口,第三個參數(shù)是用來動態(tài)調用方法的接口
* 想必介紹到這里,熟悉java反射的朋友應該想到了,動態(tài)代理是通過反射來實現(xiàn)的運行時方法調用
* */
User user = new User();
//獲得代理對象
DaGuanSi proxy = (DaGuanSi) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
@Override
//當通過代理對象調用xxx方法時就會調用下面的方法執(zhí)行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("各位好,我是代理律師");
Object invoke = method.invoke(user,args);//這里就是通過反射執(zhí)行代理類的方法,也就是間接的調用被代理類的方法
System.out.println("本代理律師發(fā)言完畢");
return invoke;
}
});
proxy.juzheng();
proxy.susong();
}
}
為了演示動態(tài)代理的優(yōu)勢,我們再通過動態(tài)代理來為上面的賣房子的例子做一下實現(xiàn),這次我們只需要將動態(tài)代理中的代理對象聲名為Seller(賣房者),接口改成賣房子的公共接口,就會動態(tài)的生成代理對象,當調用代理對象的方法時,也會調用被代理對象的方法。
package dynamic_proxy;
import static_proxy.SellHouse;
import static_proxy.Seller;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by bitsino-001 on 2019/5/17.
* 演示如何實現(xiàn)動態(tài)代理
*
*/
public class TestDynamicProxy {
public static void main(String[] args) {
//獲得代理類,需要用到JDK中的 Proxy.newProxyInstance()方法
// 在Proxy.newProxyInstance()中需要傳入三個參數(shù)
/* public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
* 第一個是被代理類的類加載器,第二個是被代理類實現(xiàn)的接口,第三個參數(shù)是用來動態(tài)調用方法的接口
* 想必介紹到這里,熟悉java反射的朋友應該想到了,動態(tài)代理是通過反射來實現(xiàn)的運行時方法調用
* */
/* User user = new User();
//獲得代理對象
DaGuanSi proxy = (DaGuanSi) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
@Override
//當通過代理對象調用xxx方法時就會調用下面的方法執(zhí)行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("各位好,我是代理律師");
Object invoke = method.invoke(user,args);//這里就是通過反射執(zhí)行代理類的方法,也就是間接的調用被代理類的方法
System.out.println("本代理律師發(fā)言完畢");
return invoke;
}
});
proxy.juzheng();
proxy.susong();*/
Seller seller = new Seller();
//獲得代理對象
SellHouse proxy = (SellHouse) Proxy.newProxyInstance(seller.getClass().getClassLoader(), seller.getClass().getInterfaces(), new InvocationHandler() {
@Override
//當通過代理對象調用xxx方法時就會調用下面的方法執(zhí)行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("各位好,我是代理律師");
Object invoke = method.invoke(seller,args);//這里就是通過反射執(zhí)行代理類的方法,也就是間接的調用被代理類的方法
System.out.println("本代理律師發(fā)言完畢");
return invoke;
}
});
proxy.price_house();
}
}