(1)經過代理,控制對象的訪問;java
(2)能夠詳細的控制訪問某個(某類)對象的方法,在調用這個方法前作前置處理,調用這個方法後作後置處理。(AOP的微實現)編程
代理模式是 AOP(Aspect Oriented Programming 面向切面編程)的核心實現機制。安全
(1)抽象角色框架
定義代理角色和真實角色的公共對外方法。ide
(2)真實角色性能
實現抽象角色,定義真實角色所須要實現的業務邏輯,供代理角色調用。測試
關注真正的業務邏輯。this
(3)代理角色spa
實現抽象角色,是真實角色的代理,經過真實角色的業務邏輯輔方法來實現抽象方法,並附加本身的操做。代理
將統一的流程控制放在代理角色中處理!
三、代理模式的使用場景
(1)安全代理: 屏蔽對真實角色的訪問;
(2)經過代理類處理遠程方法調用(RMI Remote Method Invocation 遠程方法調用);
(3)延遲加載:先加載輕量級的代理對象,真正須要再加載真實對象。
(1)靜態代理(靜態定義代理類)
(2)動態代理(動態生成代理類)
① JDK自帶的動態代理
② javassist字節碼操做庫實現
③ CGLIB
CGLIB是一個功能強大,高性能的代碼生成包。它爲沒有實現接口的類提供代理,爲JDK的動態代理提供了很好的補充。
一般可使用Java的動態代理建立代理,但當要代理的類沒有實現接口或者爲了更好的性能,CGLIB是一個好的選擇。
④ ASM底層使用指令,可維護性較差
ASM是一個java字節碼操縱框架,它能被用來動態生成類或者加強既有類的功能。
示例代碼場景:周杰倫開演唱會時,面談、籤合同、訂票等操做都是由周杰倫的經紀人來完成,唱歌部分由他本人完成,最後收款也是由經紀人來完成。
(1)建立抽象角色
1 /** 2 * 抽象角色 3 * @author CL 4 * 5 */ 6 public interface Star { 7 /** 8 * 面談 9 */ 10 void confer(); 11 /** 12 * 籤合同 13 */ 14 void signConstract(); 15 /** 16 * 訂票 17 */ 18 void bookTicket(); 19 /** 20 * 唱歌 21 */ 22 void sing(); 23 /** 24 * 收款 25 */ 26 void collectMoney(); 27 }
(2)定義真實角色
1 /** 2 * 真實身份(至關於例子中的周杰倫本人) 3 * @author CL 4 * 5 */ 6 public class RealStar implements Star { 7 8 @Override 9 public void confer() { 10 System.out.println("周杰倫去面談"); 11 } 12 13 @Override 14 public void signConstract() { 15 System.out.println("周杰倫去籤合同"); 16 } 17 18 @Override 19 public void bookTicket() { 20 System.out.println("周杰倫去訂票"); 21 } 22 23 @Override 24 public void sing() { 25 System.out.println("周杰倫去唱歌"); 26 } 27 28 @Override 29 public void collectMoney() { 30 System.out.println("周杰倫去收款"); 31 } 32 33 }
(3)定義代理角色
1 /** 2 * 代理身份(至關於例子中的周杰倫的經紀人) 3 * @author CL 4 * 5 */ 6 public class ProxyStar implements Star { 7 private Star star; 8 9 public ProxyStar(Star star) { 10 this.star = star; 11 } 12 13 @Override 14 public void confer() { 15 System.out.println("經紀人去面談"); 16 } 17 18 @Override 19 public void signConstract() { 20 System.out.println("經紀人去籤合同"); 21 } 22 23 @Override 24 public void bookTicket() { 25 System.out.println("經紀人去訂票"); 26 } 27 28 @Override 29 public void sing() { 30 star.sing(); 31 } 32 33 @Override 34 public void collectMoney() { 35 System.out.println("經紀人去收款"); 36 } 37 38 }
(4)測試
1 /** 2 * 客戶端 3 * 只和經紀人聯繫 4 * @author CL 5 * 6 */ 7 public class Client { 8 9 public static void main(String[] args) { 10 Star real = new RealStar(); 11 Star proxy = new ProxyStar(real); 12 13 //面談 14 proxy.confer(); 15 //籤合同 16 proxy.signConstract(); 17 //訂票 18 proxy.bookTicket(); 19 //唱歌 20 proxy.sing(); 21 //收款 22 proxy.collectMoney(); 23 } 24 }
控制檯輸出:
經紀人去面談
經紀人去籤合同
經紀人去訂票
周杰倫去唱歌
經紀人收款
JDK自帶的動態代理:
① 在客戶端,java.lang.reflect.Proxy
做用:動態生成代理類和對象
② 實現java.lang.reflect.InvocationHandler(處理器接口)
能夠經過invoke方法實現對真實角色的代理訪問
每次經過Proxy生成代理類對象時都要指定對應的處理器對象
(1)建立抽象角色
1 public interface Star { 2 /** 3 * 面談 4 */ 5 void confer(); 6 /** 7 * 籤合同 8 */ 9 void signConstract(); 10 /** 11 * 訂票 12 */ 13 void bookTicket(); 14 /** 15 * 唱歌 16 */ 17 void sing(); 18 /** 19 * 收款 20 */ 21 void collectMoney(); 22 }
(2)建立真實角色
1 /** 2 * 真實身份(至關於例子中的周杰倫本人) 3 * @author CL 4 * 5 */ 6 public class RealStar implements Star { 7 8 @Override 9 public void confer() { 10 System.out.println("周杰倫去面談"); 11 } 12 13 @Override 14 public void signConstract() { 15 System.out.println("周杰倫去籤合同"); 16 } 17 18 @Override 19 public void bookTicket() { 20 System.out.println("周杰倫去訂票"); 21 } 22 23 @Override 24 public void sing() { 25 System.out.println("周杰倫去唱歌"); 26 } 27 28 @Override 29 public void collectMoney() { 30 System.out.println("周杰倫去收款"); 31 } 32 33 }
(3)建立代理角色的處理器
1 import java.lang.reflect.InvocationHandler; 2 import java.lang.reflect.Method; 3 4 /** 5 * 代理角色的處理類 6 * jdk自帶的動態代理 7 * @author CL 8 * 9 */ 10 public class StarHandler implements InvocationHandler { 11 private Star realStar; 12 13 public StarHandler(Star realStar) { 14 this.realStar = realStar; 15 } 16 17 //經過invoke方法實現對真實角色的代理訪問 18 @Override 19 public Object invoke(Object proxy, Method method, Object[] args) 20 throws Throwable { 21 Object obj = null; 22 23 System.out.print("在執行真實角色的方法以前的處理,好比-->"); 24 System.out.println("面談,籤合同,訂票"); 25 26 if (method.getName().equals("sing")) { 27 obj = method.invoke(realStar, args); 28 } 29 30 System.out.print("在執行真實角色的方法以後的處理,好比-->"); 31 System.out.println("收款"); 32 33 return obj; 34 } 35 36 }
(4)測試
1 import java.lang.reflect.Proxy; 2 3 /** 4 * 測試JDK自帶的動態代理 5 * @author CL 6 * 7 */ 8 public class Client { 9 10 public static void main(String[] args) { 11 Star realStar = new RealStar(); 12 13 StarHandler handler = new StarHandler(realStar); 14 15 Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class}, handler); 16 17 proxy.sing(); 18 } 19 }
控制檯輸出:
在執行真實角色的方法以前的處理,好比-->面談,籤合同,訂票
周杰倫去唱歌
在執行真實角色的方法以後的處理,好比-->收款