--- title: Java ä»£çæ¨¡å¼è¯¦è§£ category: Java tag: - Javaåºç¡ --- ## 1. ä»£çæ¨¡å¼ ä»£çæ¨¡å¼æ¯ä¸ç§æ¯è¾å¥½çè§£ç设计模å¼ãç®åæ¥è¯´å°±æ¯ **æä»¬ä½¿ç¨ä»£ç对象æ¥ä»£æ¿å¯¹çå®å¯¹è±¡(real object)ç访é®ï¼è¿æ ·å°±å¯ä»¥å¨ä¸ä¿®æ¹åç®æ 对象çåæä¸ï¼æä¾é¢å¤çåè½æä½ï¼æ©å±ç®æ 对象çåè½ã** **ä»£çæ¨¡å¼ç主è¦ä½ç¨æ¯æ©å±ç®æ 对象çåè½ï¼æ¯å¦è¯´å¨ç®æ 对象çæä¸ªæ¹æ³æ§è¡ååä½ å¯ä»¥å¢å ä¸äºèªå®ä¹çæä½ã** 举个ä¾åï¼ä½ æ¾äºå°çº¢æ¥å¸®ä½ é®è¯ï¼å°çº¢å°±å¯ä»¥ç使¯ä»£çä½ ç代ç对象ï¼ä»£ççè¡ä¸ºï¼æ¹æ³ï¼æ¯é®è¯ã 
https://medium.com/@mithunsasidharan/understanding-the-proxy-design-pattern-5e63fe38052a
ä»£çæ¨¡å¼æéæä»£çå卿代ç两ç§å®ç°æ¹å¼ï¼æä»¬ å æ¥çä¸ä¸éæä»£ç模å¼çå®ç°ã ## 2. éæä»£ç **éæä»£çä¸ï¼æä»¬å¯¹ç®æ å¯¹è±¡çæ¯ä¸ªæ¹æ³çå¢å¼ºé½æ¯æå¨å®æçï¼_åé¢ä¼å ·ä½æ¼ç¤ºä»£ç _ï¼ï¼é常ä¸çµæ´»ï¼_æ¯å¦æ¥å£ä¸æ¦æ°å¢å æ¹æ³ï¼ç®æ 对象å代ç对象é½è¦è¿è¡ä¿®æ¹_ï¼ä¸éº»ç¦(_éè¦å¯¹æ¯ä¸ªç®æ ç±»é½åç¬åä¸ä¸ªä»£çç±»_)ã** å®é åºç¨åºæ¯é常é常å°ï¼æ¥å¸¸å¼åå ä¹çä¸å°ä½¿ç¨éæä»£ççåºæ¯ã ä¸é¢æä»¬æ¯ä»å®ç°ååºç¨è§åº¦æ¥è¯´çéæä»£çï¼ä» JVM å±é¢æ¥è¯´ï¼ **éæä»£çå¨ç¼è¯æ¶å°±å°æ¥å£ãå®ç°ç±»ã代çç±»è¿äºé½åæäºä¸ä¸ªä¸ªå®é ç class æä»¶ã** éæä»£çå®ç°æ¥éª¤: 1. å®ä¹ä¸ä¸ªæ¥å£åå ¶å®ç°ç±»ï¼ 2. å建ä¸ä¸ªä»£çç±»åæ ·å®ç°è¿ä¸ªæ¥å£ 3. å°ç®æ å¯¹è±¡æ³¨å ¥è¿ä»£çç±»ï¼ç¶åå¨ä»£çç±»çå¯¹åºæ¹æ³è°ç¨ç®æ ç±»ä¸çå¯¹åºæ¹æ³ãè¿æ ·çè¯ï¼æä»¬å°±å¯ä»¥éè¿ä»£çç±»å±è½å¯¹ç®æ 对象ç访é®ï¼å¹¶ä¸å¯ä»¥å¨ç®æ æ¹æ³æ§è¡åååä¸äºèªå·±æ³åçäºæ ã ä¸é¢éè¿ä»£ç å±ç¤ºï¼ **1.å®ä¹åéçä¿¡çæ¥å£** ```java public interface SmsService { String send(String message); } ``` **2.å®ç°åéçä¿¡çæ¥å£** ```java public class SmsServiceImpl implements SmsService { public String send(String message) { System.out.println("send message:" + message); return message; } } ``` **3.å建代çç±»å¹¶åæ ·å®ç°åéçä¿¡çæ¥å£** ```java public class SmsProxy implements SmsService { private final SmsService smsService; public SmsProxy(SmsService smsService) { this.smsService = smsService; } @Override public String send(String message) { //è°ç¨æ¹æ³ä¹åï¼æä»¬å¯ä»¥æ·»å èªå·±çæä½ System.out.println("before method send()"); smsService.send(message); //è°ç¨æ¹æ³ä¹åï¼æä»¬åæ ·å¯ä»¥æ·»å èªå·±çæä½ System.out.println("after method send()"); return null; } } ``` **4.å®é 使ç¨** ```java public class Main { public static void main(String[] args) { SmsService smsService = new SmsServiceImpl(); SmsProxy smsProxy = new SmsProxy(smsService); smsProxy.send("java"); } } ``` è¿è¡ä¸è¿°ä»£ç ä¹åï¼æ§å¶å°æå°åºï¼ ```bash before method send() send message:java after method send() ``` å¯ä»¥è¾åºç»æçåºï¼æä»¬å·²ç»å¢å äº `SmsServiceImpl` ç`send()`æ¹æ³ã ## 3. 卿代ç ç¸æ¯äºéæä»£çæ¥è¯´ï¼å¨æä»£çæ´å çµæ´»ãæä»¬ä¸éè¦é对æ¯ä¸ªç®æ ç±»é½åç¬å建ä¸ä¸ªä»£çç±»ï¼å¹¶ä¸ä¹ä¸éè¦æä»¬å¿ é¡»å®ç°æ¥å£ï¼æä»¬å¯ä»¥ç´æ¥ä»£çå®ç°ç±»( _CGLIB å¨æä»£çæºå¶_)ã **ä» JVM è§åº¦æ¥è¯´ï¼å¨æä»£çæ¯å¨è¿è¡æ¶å¨æçæç±»åèç ï¼å¹¶å è½½å° JVM ä¸çã** 说å°å¨æä»£çï¼Spring AOPãRPC æ¡æ¶åºè¯¥æ¯ä¸¤ä¸ªä¸å¾ä¸æçï¼å®ä»¬çå®ç°é½ä¾èµäºå¨æä»£çã **卿代ç卿们æ¥å¸¸å¼åä¸ä½¿ç¨çç¸å¯¹è¾å°ï¼ä½æ¯å¨æ¡æ¶ä¸çå 乿¯å¿ ç¨çä¸é¨ææ¯ãå¦ä¼äºå¨æä»£çä¹åï¼å¯¹äºæä»¬çè§£åå¦ä¹ åç§æ¡æ¶çåçä¹é常æå¸®å©ã** å°± Java æ¥è¯´ï¼å¨æä»£ççå®ç°æ¹å¼æå¾å¤ç§ï¼æ¯å¦ **JDK 卿代ç**ã**CGLIB 卿代ç**ççã [guide-rpc-framework](https://github.com/Snailclimb/guide-rpc-framework) 使ç¨çæ¯ JDK 卿代çï¼æä»¬å æ¥çç JDK 卿代çç使ç¨ã å¦å¤ï¼è½ç¶ [guide-rpc-framework](https://github.com/Snailclimb/guide-rpc-framework) 没æç¨å° **CGLIB 卿代ç** ï¼æä»¬è¿éè¿æ¯ç®åä»ç»ä¸ä¸å ¶ä½¿ç¨ä»¥åå**JDK 卿代ç**ç对æ¯ã ### 3.1. JDK å¨æä»£çæºå¶ #### 3.1.1. ä»ç» **å¨ Java å¨æä»£çæºå¶ä¸ `InvocationHandler` æ¥å£å `Proxy` ç±»æ¯æ ¸å¿ã** `Proxy` ç±»ä¸ä½¿ç¨é¢çæé«çæ¹æ³æ¯ï¼`newProxyInstance()` ï¼è¿ä¸ªæ¹æ³ä¸»è¦ç¨æ¥çæä¸ä¸ªä»£ç对象ã ```java public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) throws IllegalArgumentException { ...... } ``` è¿ä¸ªæ¹æ³ä¸å ±æ 3 ä¸ªåæ°ï¼ 1. **loader** :ç±»å è½½å¨ï¼ç¨äºå 载代ç对象ã 2. **interfaces** : 被代çç±»å®ç°çä¸äºæ¥å£ï¼ 3. **h** : å®ç°äº `InvocationHandler` æ¥å£çå¯¹è±¡ï¼ è¦å®ç°å¨æä»£ççè¯ï¼è¿å¿ é¡»éè¦å®ç°`InvocationHandler` æ¥èªå®ä¹å¤çé»è¾ã 彿们ç卿代ç对象è°ç¨ä¸ä¸ªæ¹æ³æ¶ï¼è¿ä¸ªæ¹æ³çè°ç¨å°±ä¼è¢«è½¬åå°å®ç°`InvocationHandler` æ¥å£ç±»ç `invoke` æ¹æ³æ¥è°ç¨ã ```java public interface InvocationHandler { /** * å½ä½ 使ç¨ä»£ç对象è°ç¨æ¹æ³çæ¶åå®é ä¼è°ç¨å°è¿ä¸ªæ¹æ³ */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; } ``` `invoke()` æ¹æ³æä¸é¢ä¸ä¸ªåæ°ï¼ 1. **proxy** :卿çæç代çç±» 2. **method** : ä¸ä»£ç类对象è°ç¨çæ¹æ³ç¸å¯¹åº 3. **args** : å½å method æ¹æ³çåæ° ä¹å°±æ¯è¯´ï¼**ä½ éè¿`Proxy` ç±»ç `newProxyInstance()` å建ç代ç对象å¨è°ç¨æ¹æ³çæ¶åï¼å®é ä¼è°ç¨å°å®ç°`InvocationHandler` æ¥å£çç±»ç `invoke()`æ¹æ³ã** ä½ å¯ä»¥å¨ `invoke()` æ¹æ³ä¸èªå®ä¹å¤çé»è¾ï¼æ¯å¦å¨æ¹æ³æ§è¡åååä»ä¹äºæ ã #### 3.1.2. JDK 卿代çç±»ä½¿ç¨æ¥éª¤ 1. å®ä¹ä¸ä¸ªæ¥å£åå ¶å®ç°ç±»ï¼ 2. èªå®ä¹ `InvocationHandler` å¹¶éå`invoke`æ¹æ³ï¼å¨ `invoke` æ¹æ³ä¸æä»¬ä¼è°ç¨åçæ¹æ³ï¼è¢«ä»£çç±»çæ¹æ³ï¼å¹¶èªå®ä¹ä¸äºå¤çé»è¾ï¼ 3. éè¿ `Proxy.newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)` æ¹æ³å建代çå¯¹è±¡ï¼ #### 3.1.3. 代ç ç¤ºä¾ è¿æ ·è¯´å¯è½ä¼æç¹ç©ºæ´åé¾ä»¥çè§£ï¼æä¸ä¸ªä¾åï¼å¤§å®¶æåä¸ä¸å§ï¼ **1.å®ä¹åéçä¿¡çæ¥å£** ```java public interface SmsService { String send(String message); } ``` **2.å®ç°åéçä¿¡çæ¥å£** ```java public class SmsServiceImpl implements SmsService { public String send(String message) { System.out.println("send message:" + message); return message; } } ``` **3.å®ä¹ä¸ä¸ª JDK 卿代çç±»** ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @author shuang.kou * @createTime 2020å¹´05æ11æ¥ 11:23:00 */ public class DebugInvocationHandler implements InvocationHandler { /** * 代çç±»ä¸ççå®å¯¹è±¡ */ private final Object target; public DebugInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException { //è°ç¨æ¹æ³ä¹åï¼æä»¬å¯ä»¥æ·»å èªå·±çæä½ System.out.println("before method " + method.getName()); Object result = method.invoke(target, args); //è°ç¨æ¹æ³ä¹åï¼æä»¬åæ ·å¯ä»¥æ·»å èªå·±çæä½ System.out.println("after method " + method.getName()); return result; } } ``` `invoke()` æ¹æ³: 彿们ç卿代ç对象è°ç¨åçæ¹æ³çæ¶åï¼æç»å®é ä¸è°ç¨å°çæ¯ `invoke()` æ¹æ³ï¼ç¶å `invoke()` æ¹æ³ä»£æ¿æä»¬å»è°ç¨äºè¢«ä»£ç对象çåçæ¹æ³ã **4.è·å代ç对象çå·¥åç±»** ```java public class JdkProxyFactory { public static Object getProxy(Object target) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), // ç®æ ç±»çç±»å è½½ target.getClass().getInterfaces(), // 代çéè¦å®ç°çæ¥å£ï¼å¯æå®å¤ä¸ª new DebugInvocationHandler(target) // 代ç对象对åºçèªå®ä¹ InvocationHandler ); } } ``` `getProxy()` ï¼ä¸»è¦éè¿`Proxy.newProxyInstanceï¼ï¼`æ¹æ³è·åæä¸ªç±»ç代ç对象 **5.å®é 使ç¨** ```java SmsService smsService = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl()); smsService.send("java"); ``` è¿è¡ä¸è¿°ä»£ç ä¹åï¼æ§å¶å°æå°åºï¼ ``` before method send send message:java after method send ``` ### 3.2. CGLIB å¨æä»£çæºå¶ #### 3.2.1. ä»ç» **JDK 卿代çæä¸ä¸ªæè´å½çé®é¢æ¯å ¶åªè½ä»£çå®ç°äºæ¥å£çç±»ã** **为äºè§£å³è¿ä¸ªé®é¢ï¼æä»¬å¯ä»¥ç¨ CGLIB å¨æä»£çæºå¶æ¥é¿å ã** [CGLIB](https://github.com/cglib/cglib)(_Code Generation Library_)æ¯ä¸ä¸ªåºäº[ASM](http://www.baeldung.com/java-asm)çåèç çæåºï¼å®å 许æä»¬å¨è¿è¡æ¶å¯¹åèç è¿è¡ä¿®æ¹å卿çæãCGLIB éè¿ç»§æ¿æ¹å¼å®ç°ä»£çãå¾å¤ç¥åç弿ºæ¡æ¶é½ä½¿ç¨å°äº[CGLIB](https://github.com/cglib/cglib)ï¼ ä¾å¦ Spring ä¸ç AOP 模åä¸ï¼å¦æç®æ 对象å®ç°äºæ¥å£ï¼åé»è®¤éç¨ JDK 卿代çï¼å¦åéç¨ CGLIB 卿代çã **å¨ CGLIB å¨æä»£çæºå¶ä¸ `MethodInterceptor` æ¥å£å `Enhancer` ç±»æ¯æ ¸å¿ã** ä½ éè¦èªå®ä¹ `MethodInterceptor` å¹¶éå `intercept` æ¹æ³ï¼`intercept` ç¨äºæ¦æªå¢å¼ºè¢«ä»£çç±»çæ¹æ³ã ```java public interface MethodInterceptor extends Callback{ // æ¦æªè¢«ä»£çç±»ä¸çæ¹æ³ public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable; } ``` 1. **obj** :被代çç对象ï¼éè¦å¢å¼ºçå¯¹è±¡ï¼ 2. **method** :è¢«æ¦æªçæ¹æ³ï¼éè¦å¢å¼ºçæ¹æ³ï¼ 3. **args** :æ¹æ³å ¥å 4. **proxy** :ç¨äºè°ç¨åå§æ¹æ³ ä½ å¯ä»¥éè¿ `Enhancer`ç±»æ¥å¨æè·å被代çç±»ï¼å½ä»£çç±»è°ç¨æ¹æ³çæ¶åï¼å®é è°ç¨çæ¯ `MethodInterceptor` ä¸ç `intercept` æ¹æ³ã #### 3.2.2. CGLIB 卿代çç±»ä½¿ç¨æ¥éª¤ 1. å®ä¹ä¸ä¸ªç±»ï¼ 2. èªå®ä¹ `MethodInterceptor` å¹¶éå `intercept` æ¹æ³ï¼`intercept` ç¨äºæ¦æªå¢å¼ºè¢«ä»£çç±»çæ¹æ³ï¼å JDK 卿代çä¸ç `invoke` æ¹æ³ç±»ä¼¼ï¼ 3. éè¿ `Enhancer` ç±»ç `create()`å建代çç±»ï¼ #### 3.2.3. 代ç ç¤ºä¾ ä¸åäº JDK 卿代çä¸éè¦é¢å¤çä¾èµã[CGLIB](https://github.com/cglib/cglib)(_Code Generation Library_) å®é æ¯å±äºä¸ä¸ªå¼æºé¡¹ç®ï¼å¦æä½ è¦ä½¿ç¨å®çè¯ï¼éè¦æå¨æ·»å ç¸å ³ä¾èµã ```xml