Java反射—運用反射產生jdk動態代理

來源:互聯網
上載者:User

標籤:

1.  核心類&介面

       在Java的java.lang.reflect包下提供一個Proxy類和一個InvocationHandler介面,通過使用這個類和介面可以產生jdk動態代理類或動態代理對象。

       Proxy是所有動態代理類的父類,它提供了兩個靜態方法來建立動態代理類和動態代理對象,如下:

  ? static Class<?>getProxyClass(ClassLoader loader,Class<?>... interfaces)

  ? static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

  getProxyClass返回代理類的 java.lang.Class 對象,並向其提供類載入器和介面數組。newProxyInstance返回一個指定介面的代理類執行個體,該介面可以將方法調用轉寄到指定的調用處理常式,執行代理對象的每個方法時都會被替換執行InvocationHandler對象的Invoke方法。實際上,即使採用第一種方式擷取了一個動態代理類之後,當程式需要通過該代理類來建立對象時一樣需要傳入一個InvocationHandler對象。也就是說,系統產生的每個代理對象都有一個與之關聯的InvocationHandler對象。

  從上面的兩個方法的參數可以看出,只有給我一個(或多個)介面,我們就可以產生實現了這個(或多個)介面的代理類和代理對象。


2.    兩種方式組建代理程式對象

       下面我們就用上面提到兩種方式,分別來產生一個介面(Person)的代理對象。

  2.1  介面Person
package com.tgb.reflect;/** * 目標介面 *  * @author wangzhipeng *  */public interface Person {public void walk();public void sayHello();}

  2.2  構造一個InvocationHandler類
package com.tgb.reflect;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler {/** * 執行代理對象的所有方法時都會被替換成執行如下的invoke方法 *  * proxy :代表動態代理對象; method:代表正在執行的方法 ;args :代表執行代理對象方法時傳入的實參 */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stubSystem.out.println("正在執行方法:" + method.getName());if (args != null) {System.out.println("下面是執行方法時傳入的實參:");for (Object object : args) {System.out.println(object);}} else {System.out.println("該方法調用無實參!");}return null;}}

  2.3  方式一:利用getProxyClass組建代理程式對象
package com.tgb.reflect;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;/** * 利用getProxyClass組建代理程式對象 *  * @author wangzhipeng *  */public class TestReflectProxy {@SuppressWarnings("unchecked")public static void main(String[] args) throws Exception {// 1、建立一個InvocationHandler對象InvocationHandler myInvocationHandler = new MyInvocationHandler();// 2、建立Person介面的一個代理類(擷取代理類的位元組碼)Class proxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class[] { Person.class });// 3、根據代理類的位元組碼拿到它的參數為InvocationHandler類型的構造器Constructor constructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });// 4、根據構造器建立代理對象Person person = (Person) constructor.newInstance(myInvocationHandler);// 5、調用代理對象的方法person.walk();person.sayHello();/** * 輸出結果如下: *  * 正在執行方法:walk 該方法調用無實參! *  * 正在執行方法:sayHello 該方法調用無實參! */}}

  2.4  方式二:利用newProxyInstance組建代理程式對象
package com.tgb.reflect;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;/** * 利用newProxyInstance組建代理程式對象 *  * @author wangzhipeng *  */public class TestReflectProxy2 {public static void main(String[] args) {// 1、建立一個InvocationHandler對象InvocationHandler myInvocationHandler = new MyInvocationHandler();// 2、利用Proxy類的靜態方法newProxyInstance直接產生Person介面的代理對象Person person = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[] { Person.class }, myInvocationHandler);// 3、調用代理對象的方法person.walk();person.sayHello();/** * 輸出結果如下: *  * 正在執行方法:walk 該方法調用無實參! *  * 正在執行方法:sayHello 該方法調用無實參! */}}

3.    動態代理與aop

下面我們在上面例子的基礎上再擴充一小步,類比以下aop思想原理。其實,非常簡單,上面已經提到了,執行代理對象的每個方法時都被替換執行InvocationHandler對象的Invoke方法。所以我們只需要在Invoke方法中的“反射執行目標方法(method.invoke(target,args))“的前後加入我們增強方法即可。執行個體代碼如下:

  3.1   目標介面Person
package com.tgb.reflect.aop;/** * 目標介面 *  * @author wangzhipeng *  */public interface Person {public void walk();public void sayHello();}

  3.2   目標類ZhanSan
package com.tgb.reflect.aop;/** * 目標類(實現了Person介面) *  * @author wangzhipeng *  */public class ZhanSan implements Person {@Overridepublic void sayHello() {System.out.println("我是張三---->sayHello");}@Overridepublic void walk() {System.out.println("我是張三---->walk");}}

  3.3   增強類Extend
package com.tgb.reflect.aop;/** * 增強類 *  * @author wangzhipeng *  */public class Extend {/** * 增強方法1 */public void ExtendMethod1() {System.out.println("我是增強方法一");}/** * 增強方法2 */public void ExtendMethod2() {System.out.println("我是增強方法二");}}

  3.4   InvocationHandler類MyInvocationHandler
package com.tgb.reflect.aop;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler {// 目標對象(需要被代理的對象)private Object target;public void setTarget(Object target) {this.target = target;}/** * 執行代理對象的所有方法時都會被替換成執行如下的invoke方法 */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 執行個體化一個增強類Extend extend = new Extend();// 執行增強方法1(類比spring前置增強)extend.ExtendMethod1();Object result = method.invoke(target, args);// 【執行目標方法】// 執行增強方法2(類比spring後置增強)extend.ExtendMethod2();return result;}}

  3.5   代理產生工廠MyProxyFactory
package com.tgb.reflect.aop;import java.lang.reflect.Proxy;/** * 組建代理程式的工廠 *  * @author wangzhipeng *  */public class MyProxyFactory {/* * 擷取一個目標對象(目標類必須實現介面)的代理對象 */public static Object getProxy(Object target) {// 執行個體化一個InvocationHandler類,並傳入目標對象MyInvocationHandler myInvocationHandler = new MyInvocationHandler();myInvocationHandler.setTarget(target);// 組建代理程式對象Object proxyObject = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInvocationHandler);return proxyObject;}}

  3.6   測試類別Test
package com.tgb.reflect.aop;/** * 測試類別 *  * @author wangzhipeng *  */public class Test {public static void main(String[] args) {// 建立一個原始的ZhanSan(實現了Person介面)對象作為TargetPerson zhanSan = new ZhanSan();// 利用代理工廠產生zhansan對象(Target)的代理對象Person proxyZhanSan = (Person) MyProxyFactory.getProxy(zhanSan);// 執行代理對象的方法(會執行織入的增強類(Extend)的兩個增強方法)proxyZhanSan.walk();proxyZhanSan.sayHello();}}

  3.7   結果如下


4.    總結

  Proxy類主要方法有四個(如),jdk動態代理主要是利用Proxy類的getProxyClass和newProxyInstance方法產生介面的動態代理對象,並將執行代理對象的每個方法時都被替換執行InvocationHandler對象的Invoke方法。這為Spring的aop打好了基礎。此外,實際應用中,我們一般不會單純直接產生一個(或多個)介面的代理對象,而是產生某個介面實作類別(目標類)的代理對象。




  實際上普通的java編程中我們很少用到動態代理,它最大的魅力在於編寫架構或底層基礎代碼。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Java反射—運用反射產生jdk動態代理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.