1彤蔽、代理模式的定義
為某個對象提供一種代理,以控制對這個對象的訪問
2雄妥、代理模式的實(shí)現(xiàn)要點(diǎn)
靜態(tài)代理:在編譯期就確定好代理類蟹漓,通過代理類來執(zhí)行被代理類的方法
動態(tài)代理:在運(yùn)行期才確定好代理類炕横,通過代理類來執(zhí)行被代理類的方法(框架使用)
3、應(yīng)用場景
無侵入對散落各處的方法調(diào)用進(jìn)行增強(qiáng)(AOP)牧牢,比如日志記錄看锉,性能統(tǒng)計姿锭,安全控制塔鳍,事務(wù)處理,異常處理
4呻此、實(shí)現(xiàn)舉例
靜態(tài)代理
public class StaticProxy implements GamPlayer {
private GamPlayer gamPlayer;
public StaticProxy(GamPlayer gamPlayer){
this.gamPlayer = gamPlayer;
}
public void killBoss(){
gamPlayer.killBoss();
}
public void upgrade(){
gamPlayer.upgrade();
}
public static GamPlayer getStaticProxy(GamPlayer player){
return new StaticProxy(player);
}
public static void main(String[] args) {
GamPlayer player = new GamPlayerImpl();
GamPlayer staticProxy = StaticProxy.getStaticProxy(player);
staticProxy.killBoss();
staticProxy.upgrade();
}
}
動態(tài)代理
public class DynamicProxy implements InvocationHandler {
private Object target;//被代理的對象
public DynamicProxy(Object target){
this.target = target;
}
//動態(tài)代理類調(diào)用upgrade方法轮纫,先調(diào)用InvocationHandler中的invoke,再通過invoke調(diào)用被代理類gamplayer的方法
//proxy 代理類的實(shí)例焚鲜,可以用來獲取代理對象的信息和可以將代理對象返回進(jìn)行連續(xù)調(diào)用掌唾,其他時候都無作用
//method被代理類的方法放前,args被代理類方法的參數(shù),返回值:表示當(dāng)前執(zhí)行方法的返回值
public Object invoke(Object proxy,Method method,Object[] args) throws Exception{
System.out.println("proxy = " + proxy.getClass().getName() );
System.out.println("我是前置通知"); //每個方法執(zhí)行前的前置通知
Object result = method.invoke(target,args);
System.out.println("我是后置通知"); //每個方法執(zhí)行后的后置通知
return result;
}
public static Object getDynamicProxy(Object target){
InvocationHandler invocationHandler = new DynamicProxy(target);
//通過類加載器糯彬、類方法凭语,可以反射出類的實(shí)例,調(diào)用處理方法invocationHandler撩扒,主要定義動態(tài)代理調(diào)用被代理類的方法
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),invocationHandler);
}
public static void main(String[] args) {
GamPlayer gamPlayer = new GamPlayerImpl();
GamPlayer dynamicGamPlayer =(GamPlayer) DynamicProxy.getDynamicProxy(gamPlayer);
dynamicGamPlayer.upgrade();
dynamicGamPlayer.killBoss();
}
}
cglib 實(shí)現(xiàn)動態(tài)代理(非實(shí)現(xiàn)接口的類的代理)
public class CglibDynamicProxy implements MethodInterceptor {
public Object target;//被代理對象
public CglibDynamicProxy(Object target){
this.target = target;
}
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("這里可以插入執(zhí)行關(guān)鍵代碼之前的邏輯");
System.out.println(String.format("object is %",object.getClass().getName()));
Object result = methodProxy.invokeSuper(object,args);
System.out.println("這里可以插入執(zhí)行關(guān)鍵代碼之后的邏輯");
return result;
}
public static Object getCglibDynamicProxy(Object target){
CglibDynamicProxy methodInterceptor = new CglibDynamicProxy(target);
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(methodInterceptor);
return enhancer.create();
}
public static void main(String[] args) {
GamPlayerImpl gamPlayer = new GamPlayerImpl();
GamPlayerImpl cglibDynProxy = (GamPlayerImpl) CglibDynamicProxy.getCglibDynamicProxy(gamPlayer);
cglibDynProxy.killBoss();
cglibDynProxy.upgrade();
}
}