為一個對象提供一個替身,來控制這個對象的通路。通過代理對象通路目标對象,這樣做的好處是可以在目标對象實作的基礎上,增強額外的功能操作
被代理的對象可以是遠端對象,建立開銷大的對象,需要安全控制的對象
代理模式主要分為三種 靜态代理,動态代理(也叫接口代理、jdk代理),cglib代理(可以在記憶體建立對象而不需要實作接口,屬于動态代理的範疇)
靜态代理
被代理類和代理類需要實作相同接口或者繼承父類
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
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代理
在記憶體種建構一個子類對象進而實作對目标對象功能擴充
需要四個包-注意版本
目标類
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;
}
}