天天看點

12.代理模式

為一個對象提供一個替身,來控制這個對象的通路。通過代理對象通路目标對象,這樣做的好處是可以在目标對象實作的基礎上,增強額外的功能操作

被代理的對象可以是遠端對象,建立開銷大的對象,需要安全控制的對象

代理模式主要分為三種 靜态代理,動态代理(也叫接口代理、jdk代理),cglib代理(可以在記憶體建立對象而不需要實作接口,屬于動态代理的範疇)

靜态代理

被代理類和代理類需要實作相同接口或者繼承父類

12.代理模式
public interface BuyHouse {
    public void housePrice();
}           
public class Buyer implements BuyHouse {
    @Override
    public void housePrice() {
        System.out.println("顧客要去買房子");
    }
}           
public class BuyerProxy implements BuyHouse {
    BuyHouse buyer;

    public BuyerProxy(BuyHouse buyer) {
        this.buyer = buyer;
    }

    @Override
    public void housePrice() {
        System.out.println("中介開始談條件");
        buyer.housePrice();
        System.out.println("房子買下來簽合約");
    }

    public static void main(String[] args) {
        BuyerProxy buyerProxy = new BuyerProxy(new Buyer());
        buyerProxy.housePrice();
    }
}           

優點:可以動态的擴充代理類的功能而不影響到原來的被代理類的功能

缺點:兩者實作同一個接口,是以一旦接口增加方法,目标類和代理類都需要維護

動态代理--動态展現在并沒有把對象固定死

代理對象不需要實作接口但是被代理對象還是要實作接口,這其種是使用了jdk的api

12.代理模式
public class JDKProxy {
    Object object;

    public JDKProxy(Object object) {
        this.object = object;
    }

    public Object getProxyInstance(){
        //參數說明
        //第一個參數是對象的類加載器
        //第二個對象是類對應所有的接口
        //第三個參數是即将調用目标類的方法
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("這是jdk代理買房");
                //通過反射來調用方法
                Object invoke = method.invoke(object, args);
                System.out.println("完成購房");
                //傳回目标方法
                return invoke;
            }
        });
    }

    public static void main(String[] args) {
        Buyer buyer=new Buyer();
        JDKProxy jdkProxy=new JDKProxy(buyer);
        //注意這裡在使用的時候要轉成相應的接口
        BuyHouse proxyInstance = (BuyHouse)jdkProxy.getProxyInstance();
        proxyInstance.housePrice();

    }
}           

Cglib代理(子類代理)

如果被代理類沒有實作任何接口,那麼我們就可以使用cglib代理

在記憶體種建構一個子類對象進而實作對目标對象功能擴充

需要四個包-注意版本

12.代理模式

目标類

public class BuyHouse {
    public void buyHouse(){
        System.out.println("我不繼承東西,但是我要買房");
    }
}           

代理類

public class ProxyFactory implements MethodInterceptor {
    Object object;

    public ProxyFactory(Object object) {
        this.object = object;
    }
    //傳回一個代理對象
    public Object getProxyInstance(){
        //建立一個工具類
        Enhancer enhancer = new Enhancer();
        //設定父類
        enhancer.setSuperclass(object.getClass());
        //設定回調函數
        enhancer.setCallback(this);
        //傳回子類對象
        return enhancer.create();
    }
    //這個方法會調用目标的方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib代理模式開始啦");
        //這裡用的也是反射
        Object invoke = method.invoke(object, objects);
        System.out.println("買房結束");
        return invoke;
    }

}           
12.代理模式
12.代理模式