靜態代理與動態代理
靜態代理
靜態代理:特征是代理類和目標物件的類都是在編譯期間確定下來,不利于程式的擴展,
同時,每一個代理類只能為一個介面服務,這樣一來程式開發中必然產生過多的代理,
最好可以通過一個代理類完成全部的代理功能,
動態代理
動態代理:
使用一個代理將物件包裝起來,然后用該代理物件取代院士物件,任何對原始物件的呼叫都要通過代理,代理物件決定是否以及何時將
方法呼叫到原始物件上
動態代理是指客戶通過代理類來呼叫其他物件的方法,并且是在程式運行時根據需要動態創建目標類的代理物件
動態代理的使用場合:
>除錯
>遠程方法呼叫
動態代理相比靜態代理的優點:
抽象角色中(介面)宣告的所有方法都被轉移到呼叫處理器一個集中的方法中處理,這樣,我們可以更加靈活和同一的處理眾多的方法
靜態代理的創建流程
創建介面
interface ClothFactory{
void produceCloth();
}
創建代理類
注意點:
1.代理類中應當宣告被代理類的物件
2.應當宣告引數為被代理類物件的構造器
class ProxyClothFactory implements ClothFactory{
private ClothFactory factory;//使用被代理類物件進行實體化
public ProxyClothFactory(ClothFactory factory){
this.factory = factory;
}
@Override
public void produceCloth() {
System.out.println("代理工廠準備作業");
factory.produceCloth();
System.out.println("代理工廠收尾作業");
}
}
創建被代理類
class NikeClothFactory implements ClothFactory{
@Override
public void produceCloth() {
System.out.println("Nike工廠生產一批衣服");
}
}
方法的測驗
public class StaticProxyTest {
public static void main(String[] args) {
//造被代理類物件
NikeClothFactory nk = new NikeClothFactory();
//造代理類
ProxyClothFactory pcf = new ProxyClothFactory(nk);
//呼叫方法
pcf.produceCloth();
}
}
輸出結果:
代理工廠準備作業
Nike工廠生產一批衣服
代理工廠收尾作業
動態代理的創建流程
創建介面
interface Human{
String getBelief();
void eat(String food);
}
創建被代理類
class superMan implements Human{
@Override
public String getBelief() {
return "I believe i can fly";
}
@Override
public void eat(String food) {
System.out.println("喜歡吃" + food);
}
}
創建InvocationHandler的實作類
注意:
1.此類中宣告的屬性obj即為被代理類的物件
2.InvocationHandler中重寫的invoke方法:當通過代理類的物件呼叫某個方法,就會直接呼叫如下的invoke方法
此方法中需要填入三個引數
>引數1:被代理類的物件,
>引數2:method代表的是代理類的物件呼叫的方法,因此要將被代理類要執行的方法宣告在invoke方法中.
>引數3:反射中invoke方法需要提供的引數
3.method呼叫的invoke方法,是Method類下提供的,此方法可以讓引數1所提供的類呼叫method所代表的方法,
class myInvocationHandler implements InvocationHandler{
private Object obj;//雖然宣告為Object,但是賦值時需要使用被代理類的物件進行賦值
public void bind(Object obj){
this.obj = obj;
}
//當我們通過代理類的物件,呼叫方法a時,就會自動的呼叫如下的方法,invoke
//當代理類的物件呼叫方法時,會自動呼叫handler中的方法,所以就需要將被代理類要執行的方法a的功能宣告在invoke中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//引數一:代理類的物件,引數二;代理類的物件需要呼叫的方法,
//此時method就是代理類物件呼叫的方法,此方法也就作為了被代理類物件瑤呼叫的方法
//obj:被代理類的物件
Object returnvalue =method.invoke(obj,args);
//上述方法的回傳值就作為當前類中invoke方法中的回傳值
return returnvalue;
}
}
創建動態代理類
動態代理類主要用處是用來動態的創建被代理類的代理類物件
注意:
1.創建一個方法用來動態創建被代理類的物件
2.需要借助java.lang.reflect 包中的 Proxy 類的newProxyInstance方法
3.newProxyInstance:此方法中有三個引數
>引數1: 被代理類的加載器
>引數2:被代理類實作的介面
>引數3:InvocationHandler介面的實作類的物件
4.此類創建代理類之后,當代理類呼叫方法時,會自動呼叫InvocationHandler的實作類中重寫的invoke方法,
class ProxyFactory{
public static Object getProxyInstance(Object obj){//obj:被代理類的物件
//創建invocationHandler的物件
myInvocationHandler handler = new myInvocationHandler();
//呼叫反射API下的類:Proxy
//Proxy.newProxyInstance:創建一個代理類的物件,
// 引數一:被代理類的加載器,引數二:介面,引數三:介面InvocationHandler的實作類
handler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
}
}
動態代理的測驗
public class ProxyTest {
public static void main(String[] args) {
superMan superMan = new superMan();
//創建了代理類物件
Human supe =(Human) ProxyFactory.getProxyInstance(superMan);
//當通過代理類物件呼叫方法時,會自動的呼叫被代理類中同名的方法
System.out.println(supe.getBelief());
supe.eat("水果");
System.out.println("*******************體現動態性*********");
NikeClothFactory nikeClothFactory = new NikeClothFactory();
//動態創建代理類的物件
ClothFactory proxyInstance =(ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
proxyInstance.produceCloth();
}
}
輸出結果:
I believe i can fly
喜歡吃水果
**********體現動態性
Nike工廠生產一批衣服
動態代理與AOP
AOP:Aspect Orient Programming
AOP代理的方法:創建一個包含通用方法的類,將需要的通用方法加入invoke中即可,(現在還不會,等會了以后再回來補齊阿巴阿巴),
總結:TMD好難(×)
動態代理相比靜態代理,其運用了java中的反射機制,從而可以更加的靈活,
兩者的創建程序基本相同,即:
1.需要有共同實作的介面
2.需要創建被代理類
不同之處:
1.動態代理需要實作InvocationHandler介面,
2.動態代理的代理類需要使用Proxy類的方法靈活創建被代理類的物件
只是初學萌新的一些理解,希望大佬指正,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/258934.html
標籤:java
