a、先定義一個接口,這個接口中的方法是「目標方法」java
package com.brickworkers; public interface Sky { public void rain(); }
b、接着寫一個這個接口的具體實現:spring
package com.brickworkers; public class SkyImpl implements Sky{ @Override public void rain() { System.out.println("it`s raining"); } }
c、若是要完成動態代理,首先須要定義一個InvocationHandler接口的子類:ide
package com.brickworkers; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyInvocationHandler implements InvocationHandler { //目標對象 private Object obj = null; //獲取目標對象的代理對象 public Object getProxy(Object obj){ this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } //控制執行目標對象的方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("目標對象方法執行以前"); Object result = method.invoke(obj, args); System.out.println("目標對象方法執行以後"); return result; } }
d:JDK動態代理測試類:測試
package com.brickworkers; public class ProxyTest { public static void main(String[] args) { //實例化InvocationHandler MyInvocationHandler myInvocationHandler = new MyInvocationHandler(); //生產代理對象 Sky sky = (Sky) myInvocationHandler.getProxy(new SkyImpl()); sky.rain(); } } //執行結果: 目標對象方法執行以前 // it`s raining // 目標對象方法執行以後
爲何JDK動態代理只能侷限於接口呢?查閱了一些技術文檔和JDK動態代理的源碼,發如今反編譯產生的proxyTest.class中,類的定義以下:this
import dynamic.proxy.UserService; import java.lang.reflect.*; public final class $ProxyTest extends Proxy implements Sky { ...... }
從反編譯的源碼能夠看出,proxyTest繼承了Proxy,然而在Java中只支持單繼承,可是能夠實現多個接口,因此JDK動態代理只能侷限於接口。spa
那麼JDK實現動態代理須要實現類經過接口定義業務方法,對於沒有接口的類,要實現動態代理要怎麼辦呢?這個時候就須要CGLib動態代理了。.net
CGLib採用了很是底層的字節碼技術,其原理是經過字節碼技術爲一個類建立子類,並在子類中採用方法攔截的技術攔截全部分類方法的調用,順勢織入和橫切邏輯。-http://blog.csdn.net/yakoo5/article/details/9099133/代理
a、定義一個目標對象:對象
package com.brickworkers; public class Color { public void showColor(){ System.out.println("red"); } }
b、若是要完成動態代理,首先須要定義一個MethodInterceptor接口的子類:
package com.brickworkers; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class MyCglib implements MethodInterceptor { //目標對象 private Object obj = null; public Object getProxy(Object obj){ this.obj = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); // 回調方法 enhancer.setCallback(this); // 建立代理對象 return enhancer.create(); } @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("目標對象方法執行以前"); Object result = methodProxy.invoke(obj, args); System.out.println("目標方法執行以後"); return result; } }
c、CGLib動態代理測試類:
package com.brickworkers; public class CGLibTest { public static void main(String[] args) { MyCglib myCglib = new MyCglib(); Color color = (Color) myCglib.getProxy(new Color()); color.showColor(); } } //執行結果:目標對象方法執行以前 // red // 目標方法執行以後
由於CGLib動態代理是建立一個子類來實現的,那麼對於繼承的定義,final類是沒法進行代理的。