百度云 做網(wǎng)站/濟(jì)南百度推廣開戶
代理可以進(jìn)一步劃分為靜態(tài)代理和動(dòng)態(tài)代理,代理模式在實(shí)際的生活中場(chǎng)景很多,例如中介、律師、代購(gòu)等行業(yè),都是簡(jiǎn)單的代理邏輯,在這個(gè)模式下存在兩個(gè)關(guān)鍵角色:
目標(biāo)對(duì)象角色:即代理對(duì)象所代表的對(duì)象。
代理對(duì)象角色:內(nèi)部含有目標(biāo)對(duì)象的引用,可以操作目標(biāo)對(duì)象
一、靜態(tài)代理
目標(biāo)對(duì)象角色
public class Target {public void execute(){System.out.println("Target execute...");}
}
代理對(duì)象角色
public class ProxyObj {private Target target;public ProxyObj(Target target){this.target=target;}public void invoke(){before();target.execute();after();}public void before(){System.out.println("before...");}public void after(){System.out.println("after...");}
}
public class Proxy {public static void main(String[] args) {Target target = new Target();ProxyObj proxy = new ProxyObj(target);proxy.invoke();}
}
代理模式的本質(zhì)是在目標(biāo)對(duì)象的方法前后置入增強(qiáng)操作
二、動(dòng)態(tài)代理
首先看兩個(gè)核心類,這里簡(jiǎn)述下概念,看完基本過程再細(xì)聊:
-
Proxy-創(chuàng)建代理對(duì)象,核心參數(shù):
- ClassLoader:(目標(biāo)類)加載器;
- Interfaces:(目標(biāo)類)接口數(shù)組;
- InvocationHandler:代理調(diào)用機(jī)制;
-
InvocationHandler-代理類調(diào)用機(jī)制:
- invoke:這個(gè)上篇說的反射原理;
- method:反射類庫(kù)中的核心API;
目標(biāo)對(duì)象和接口
interface IUser {Integer update (String name) ;
}
class UserService implements IUser {@Overridepublic Integer update(String name) {Integer userId = 99 ;System.out.println("UserId="+userId+";updateName="+name);return userId ;}
}
代理對(duì)象執(zhí)行機(jī)制
class UserHandler implements InvocationHandler {private Object target ;public UserHandler (Object target){this.target = target ;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before()...");Object result = method.invoke(target, args);System.out.println("after()...");return result;}
}
具體使用:
public class Proxy02 {public static void main(String[] args) {/** 生成$Proxy0的class文件*/System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");/** 目標(biāo)對(duì)象信息*/IUser userService = new UserService();ClassLoader classLoader = userService.getClass().getClassLoader();Class<?>[] interfaces = UserService.class.getInterfaces() ;/** 創(chuàng)建代理對(duì)象*/InvocationHandler userHandler = new UserHandler(userService);/** 代理類對(duì)象名* proxyClassName=com.java.proxy.$Proxy0*/String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();System.out.println("proxyClassName="+proxyClassName);/** 具體業(yè)務(wù)實(shí)現(xiàn)模擬*/IUser proxyUser1 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);IUser proxyUser2 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);proxyUser1.update("cicada") ;proxyUser2.update("smile") ;}
}
?
JDK源碼
IUser proxyUser = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
Proxy提供的靜態(tài)方法newProxyInstance()
,通過各個(gè)參數(shù)的傳入,構(gòu)建一個(gè)新的代理Class對(duì)象,即$Proxy0類的結(jié)構(gòu)信息,這里再回首看下三個(gè)核心參數(shù):
-
ClassLoader:基于JVM運(yùn)行過程,所以需要獲取目標(biāo)類UserService的類加載器;
-
Interfaces:目標(biāo)類UserService實(shí)現(xiàn)的接口,從面向?qū)ο髞砜紤],接口與實(shí)現(xiàn)分離,代理類通過實(shí)現(xiàn)IUser接口,模擬目標(biāo)類的需求;
-
InvocationHandler:代理類提供的功能封裝即UserHandler,可以在目標(biāo)方法調(diào)用前后做增強(qiáng)處理