一、代理的簡要介紹
2、代理模式的定義:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
3、作用:增強一個類中的某個方法.對程序進行擴展,Spring框架中AOP。
二、
- 動態代理它可以直接給某一個目標(被代理 對象)對象(實現了某個或者某些接口)生成一個代理對象,而不需要代理類存在,如上圖中經理人需要存在。
- 動態代理與代理模式原理是一樣的,只是它沒有具體的代理類,直接通過反射生成了一個代理對象
2、動態代理的分類
- spring中動態代理:cglib 繼承
3、動態代理作用
- 最終是學習AOP(面向切面編程),它與裝飾者模式有點相似,它比裝飾者模式還要靈活!
三、
-
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一個代理對象
-
參數1:ClassLoader loader 代理對象的類加載器 一般使用被代理對象的類加載器
-
參數2:Class<?>[] interfaces 代理對象的要實現的接口 一般使用的被代理對象實現的接口
-
參數3:InvocationHandler h (接口)執行處理類
-
-
InvocationHandler中的invoke(Object proxy, Method method, Object[] args)方法:調用代理類的任何方法,此方法都會執行
-
參數3.1:代理對象(慎用)
-
參數3.2:當前執行的方法
-
參數3.3:當前執行的方法運行時傳遞過來的參數
-
返回值:當前方法執行的返回值
-
-
2、Proxy.newProxyInstance方法參數介紹
- ClassLoader:類加載器!
- 它是用來加載器的,把.class文件加載到內存,形成Class對象!
- Class[] interfaces:指定要實現的接口們
- InvocationHandler:代理對象的所有方法(個別不執行,getClass())都會調用InvocationHandler的invoke()方法。
3、InvocationHandler方法參數介紹
public Object invoke(Object proxy, Method method, Object[] args);
這個invoke()方法在什么時候被調用!在調用代理對象所實現接口中的方法時
- Object proxy:當前對象,即代理對象!在調用誰的方法!
- Method method:當前被調用的方法(目標方法)
- Object[] args:實參!
4、簡單示例
1 import org.junit.Test; 2 import java.lang.reflect.InvocationHandler; 3 import java.lang.reflect.Method; 4 import java.lang.reflect.Proxy; 5 6 public class ProxyDemo { 7 @Test 8 public void test(){ 9 Person woman = new Woman(); 10 Person person =(Person) Proxy.newProxyInstance(woman.getClass().getClassLoader(), 11 woman.getClass().getInterfaces(), 12 new InvocationHandler() { 13 @Override 14 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 15 //增強sleep方法 16 if ("sleep".equals(method.getName())) { 17 System.out.println("大字睡姿....."); 18 return null; 19 } 20 return method.invoke(woman, args); 21 } 22 }); 23 person.eat(); 24 person.sleep(); 25 String s = person.run("快步跑"); 26 System.out.println(s); 27 } 28 29 interface Person{ 30 void eat(); 31 void sleep(); 32 String run(String state); 33 } 34 35 class Woman implements Person{ 36 37 @Override 38 public void eat() { 39 System.out.println("小口吃..."); 40 } 41 42 @Override 43 public void sleep() { 44 System.out.println("淑女睡..."); 45 } 46 47 @Override 48 public String run(String state) { 49 return "Woman" + state + "......"; 50 } 51 } 52 }
四、動態代理模型
- 目標對象:被增強的對象
- 代理對象:需要目標對象,然后在目標對象上添加了增強后的對象!
- 目標方法:增強的內容
- 代理對象 = 目標對象 + 增強
五、案例
案例1:Waiter
1 package demo2;
2
3 import org.junit.Test; 4 import java.lang.reflect.InvocationHandler; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 8 public class Demo2 { 9 @Test 10 public void fun1() { 11 Waiter manWaiter = new ManWaiter(); 12 /* 13 * 給出三個參數,來創建方法,得到代理對象 14 * */ 15 ClassLoader loader = this.getClass().getClassLoader(); 16 Class[] interfaces = {Waiter.class}; 17 InvocationHandler h = new WaiterInvocationHandler(manWaiter);//參數manWaiter類表示目標對象 18 //得到代理對象,代理對象就是在目標對象的基礎上進行了增強的對象! 19 Waiter waiterProxy = (Waiter) Proxy.newProxyInstance(loader,interfaces,h); 20 waiterProxy.serve();//前面添加"你好",后面添加"再見" 21 22 } 23 } 24 class WaiterInvocationHandler implements InvocationHandler { 25 private Waiter waiter;//目標對象 26 27 public WaiterInvocationHandler(Waiter waiter) { 28 this.waiter = waiter; 29 } 30 @Override 31 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 32 System.out.println("您好!"); 33 this.waiter.serve();//調用目標對象的目標方法 34 System.out.println("再見!"); 35 return null; 36 } 37 }
1 package demo2;
2
3 public class ManWaiter implements Waiter { 4 @Override 5 public void serve() { 6 System.out.println("服務中..."); 7 } 8 }
1 package demo2;
2
3 //服務
4 public interface Waiter { 5 //服務 6 public void serve(); 7 }
案例2:
1 /**
2 * 目標是讓目標對象和增強都可以切換!
3 */
4 public class Demo3 {
5 @Test 6 public void fun1() { 7 ProxyFactory factory = new ProxyFactory(); 8 factory.setTargetObject(new ManWaiter()); 9 factory.setBeforeAdvice(new BeforeAdvice() { //設置前置增強 10 @Override 11 public void before() { 12 System.out.println("您好!"); 13 } 14 }); 15 factory.setAfterAdvice(new AfterAdvice() { //設置后置增強 16 @Override 17 public void after() { 18 System.out.println("再見!"); 19 } 20 }); 21 22 Waiter waiter = (Waiter) factory.createProxy(); 23 waiter.serve(); 24 } 25 }
1 package demo3;
2
3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 7 /** 8 * 它用來生成代理對象 9 * 它需要所有的參數 10 * 目標對象 11 * 增強 12 */ 13 /* 14 * 1、創建代理工廠 15 * 2、給工廠設置三樣東西: 16 * 目標對象:setTargetObject(XXX); 17 * 前置增強:setBeforeAdvice(該接口的實現) 18 * 后置增強:setAfterAdvice(該接口的實現) 19 * 3、調用createProxy()得到代理對象 20 * 執行代理對象方法時: 21 * 執行BeforeAdvice的before() 22 * 目標對象的目標方法 23 * 執行AfterAdvice的after() 24 * */ 25 public class ProxyFactory { 26 private Object targetObject;//目標對象 27 private BeforeAdvice beforeAdvice;//前置增強 28 private AfterAdvice afterAdvice;//后置增強 29 30 //用來生成代理對象 31 public Object createProxy() { 32 /* 33 * 1、給出三大參數 34 * */ 35 ClassLoader loader = this.getClass().getClassLoader(); 36 Class[] interfaces = targetObject.getClass().getInterfaces(); 37 InvocationHandler h = new InvocationHandler() { 38 @Override 39 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 40 /* 41 * 在調用代理對象的方法時會執行這里的內容 42 * */ 43 //執行前置增強 44 if (beforeAdvice != null) { 45 beforeAdvice.before(); 46 } 47 Object result = method.invoke(targetObject,args);//執行目標對象的目標方法 48 //執行后置增強 49 if (afterAdvice != null) { 50 afterAdvice.after(); 51 } 52 return result; 53 } 54 }; 55 //2、得到代理對象 56 Object proxObject = Proxy.newProxyInstance(loader,interfaces,h); 57 return proxObject; 58 } 59 public Object getTargetObject() { 60 return targetObject; 61 } 62 public void setTargetObject(Object targetObject) { 63 this.targetObject = targetObject; 64 } 65 public BeforeAdvice getBeforeAdvice() { 66 return beforeAdvice; 67 } 68 public void setBeforeAdvice(BeforeAdvice beforeAdvice) { 69 this.beforeAdvice = beforeAdvice; 70 } 71 public AfterAdvice getAfterAdvice() { 72 return afterAdvice; 73 } 74 public void setAfterAdvice(AfterAdvice afterAdvice) { 75 this.afterAdvice = afterAdvice; 76 } 77 }
1 /**
2 * 前置增強
3 */
4 public interface BeforeAdvice {
5 public void before(); 6 }
1 /**
2 * 后置增強
3 */
4 public interface AfterAdvice {
5 public void after(); 6 }
案例2類圖: