橫切關注點: 跨越應用程序多個模塊的功能.java
① 、代碼混亂: 每一個方法在處理核心邏輯的同時還必須兼顧其餘多個關注點.編程
② 、代碼分散: 以日誌需求爲例, 只是爲了知足這個單一需求, 就不得不在多個模塊裏屢次重相復同的日誌代碼. 若是日誌需求發生變化, 必須修改全部模塊. 這些相似的需求包括驗證, 事務等.設計模式
③ 、代碼膨脹:愈來愈多的非業務需求(日誌和驗證)加入後, 原有的方法急劇膨脹.數組
① 、Proxy 提供用於建立動態代理類和代理對象的靜態方法, 它也是全部動態代理類的父類.框架
② 、Proxy 提供了兩個方法來建立動態代理類和動態代理實例ide
咱們經過代碼來進行理解:模塊化
接口的代碼:spa
1 package cn.vincent.porxy; 2 3 public interface ArithmeticCalculator { 4 5 int add(int i, int j); 6 7 int sub(int i, int j); 8 9 void mul(int i, int j); 10 11 void div(int i, int j); 12 13 14 }
接口實現類的代碼:設計
1 package cn.vincent.porxy; 2 3 public class ArithmeticCalculatorImpl implements ArithmeticCalculator { 4 5 @Override 6 7 public int add(int i, int j) { 8 9 return i + j; 10 11 } 12 13 @Override 14 15 public int sub(int i, int j) { 16 17 return i - j; 18 19 } 20 21 @Override 22 23 public void mul(int i, int j) { 24 25 System.out.println(i * j); 26 27 } 28 29 @Override 30 31 public void div(int i, int j) { 32 33 System.out.println(i / j); 34 35 } 36 37 }
動態代理類實現的代碼:代理
1 package cn.vincent.porxy; 2 3 import java.lang.reflect.InvocationHandler; 4 5 import java.lang.reflect.Method; 6 7 import java.lang.reflect.Proxy; 8 9 import org.junit.Test; 10 11 12 public class TestPorxy { 13 14 /** 15 16 * 關注點: 17 18 * 19 20 * 1.獲取須要被代理的目標對象。 21 22 * 23 24 * 2. Proxy.newProxyInstance(loader, interfaces, h); 25 26 * public static Object newProxyInstance(ClassLoader loader, 27 28 * Class<?>[] interfaces, 29 30 * InvocationHandler h) 31 32 * 經過使用代理類調用 靜態方法 newProxyInstance 返回一個指定接口的代理類實例, 33 34 * 通常狀況下其返回的是被代理的目標對象接口類型的!該接口能夠將方法調用指派到指* 定的調用處理程序。 35 36 * 37 38 * 對於 newProxyInstance 方法中參數都表明什麼? 39 40 * ClassLoader loader : 類加載器一般使用和被代理的對象的類加載器相同. 41 42 * 43 44 * Class<?>[] interfaces:該參數必須是一個接口類型的數組.其中若代理對象不須要 45 46 * 額外實現被代理的目標對象實現的接口外的 47 48 * 額外的接口類型,能夠使用 target.getClass().getInterfaces(),來表示目標對象*實現的接口 49 50 * 51 52 * InvocationHandler h :一般使用匿名內部類的方式。 53 54 * 對於 匿名內部類InvocationHandler中的invoke 方法 中的參數。 55 56 * public Object invoke(Object proxy, Method method, Object[] args) *throws Throwable { 57 58 * 59 60 * Object result = method.invoke(target, args); 61 62 * return result; 63 64 * } 65 66 * Object proxy : 指的是正在被返回的那個代理對象,通常不使用! 67 68 * Object[] args : 傳入的參數。 69 70 * Method method : 經過調用 invoke(Object obj, Object ... args),將被代 71 72 * 理的對象及參數傳入, 73 74 * method.invoke(target, args); 75 76 * 實現動態代理。 77 78 */ 79 80 @Test 81 82 public void test() { 83 84 85 ArithmeticCalculator target = new ArithmeticCalculatorImpl(); 86 87 Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), 88 89 // new Class[]{ArithmeticCalculator.class}, 90 91 target.getClass().getInterfaces(), 92 93 new InvocationHandler() { 94 95 @Override 96 97 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 98 99 Object result = method.invoke(target, args); 100 101 return result; 102 103 } 104 105 }); 106 107 ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) proxy; 108 109 int result = arithmeticCalculator.add(1, 1); 110 111 112 System.out.println(result); 113 114 } 115 116 }