代理設(shè)計模式:
1.真實對象
2.代理對象
3.抽象對象(抽象功能)
代理設(shè)計模式優(yōu)點:
1.保護(hù)真實對象
2.讓真實對象職責(zé)更明確
3.擴(kuò)展
靜態(tài)代理:
由代理對象代理所有真實對象的功能沛硅,需要自己編寫代理類,每個代理的功能需要單獨編寫碱璃。
真實對象:
package com;
public class President implements Gongneng {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public President(String name) {
this.name = name;
}
public void talk() {
System.out.println("talk");
}
}
代理對象:
package com;
public class StaticProxy implements Gongneng {
private President president = new President("pre");
@Override
public void talk() {
System.out.println("proxy talk");
president.talk();
}
}
抽象接口:
package com;
public interface Gongneng {
public void talk();
}
Test類:
package com;
public class TestDemo {
public static void main(String[] args) {
StaticProxy proxy = new StaticProxy();
proxy.talk();
}
}
靜態(tài)代理缺點:當(dāng)代理功能比較多時购撼,代理類中方法需要寫很多呢蛤。
動態(tài)代理:
為解決靜態(tài)代理需要頻繁編寫代理功能方法的缺點。
分類:JDK、CGLIB
JDK動態(tài)代理:
與CGLIB動態(tài)代理對比:
1.優(yōu)點:JDK自帶音羞,不需要導(dǎo)入額外jar包
2.缺點:真實對象必須實現(xiàn)接口;采用反射機(jī)制十办,效率比較低
代理類:(相當(dāng)于處理程序)
package com;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyOb implements InvocationHandler {
private ProxyedMain proxyedMain = new ProxyedMain();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("預(yù)約時間");
Object result = method.invoke(proxyedMain, args);
return result;
}
}
真實對象類:
package com;
public class ProxyedMain implements Gongneng {
@Override
public void chifan() {
System.out.println("吃飯");
}
@Override
public void mubiao() {
System.out.println("目標(biāo)");
}
}
程序會根據(jù)接口創(chuàng)建一個對象秀撇,之后當(dāng)調(diào)用該對象的方法時會調(diào)用invoke方法(即處理程序)。
package com;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
// 三個參數(shù)分別代表類加載器向族,實現(xiàn)接口呵燕,處理程序,返回代理對象
Gongneng gongneng = (Gongneng) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{Gongneng.class}, new ProxyOb());
gongneng.chifan();
}
}
Proxy.newProxyInstance中第一個參數(shù)表示反射時使用的類加載器件相,第二個參數(shù)表示Proxy需要實現(xiàn)什么接口再扭,第三個參數(shù)表示通過接口調(diào)用方法時,需要調(diào)用哪個類的invoke方法
CGLIB動態(tài)代理:
優(yōu)點:基于字節(jié)碼夜矗,生成真實對象的子類泛范,運行效率高于JDK,不需要實現(xiàn)接口
缺點:第三方非JDK功能紊撕,需要額外導(dǎo)入jar包
package com;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ProxyOb implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("預(yù)約時間");
// invoke調(diào)用子類重寫方法
// method.invoke(o,objects);
Object invokeSuper = methodProxy.invokeSuper(o, objects);
return invokeSuper;
}
}
package com;
import net.sf.cglib.proxy.Enhancer;
public class Test {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ProxyedMain.class);
enhancer.setCallback(new ProxyOb());
ProxyedMain o = (ProxyedMain) enhancer.create();
o.chifan();
}
}