代理模式是爲了提供額外或不一樣的操做,而插入的用來替代」實際」對象的對象,這些操做涉及到與」實際」對象的通訊,所以代理一般充當中間人角色。java
java中經常使用的動態代理模式爲jdk動態代理和cglib動態代理。框架
瞭解動態代理以前,須要先了解一下java中的反射,反射在框架中的應用很是普遍,它可以配置:類的全限定名,方法和參數。在運行時,動態的完成類的初始化,或者反射調用某些方法。ide
咱們能夠經過Class.forName()方法加載類,並用getConstructor方法配置參數。例:測試
object = (goodsServiceImpl)=Class.forName("com.xjx.test.goodsServiceImpl").getConstructor(String.class).newInstance("計算機");
jdk動態代理由java.lang.reflect.*包提供,它必須藉助一個接口才能實現代理。this
咱們舉個例子來實現jdk動態代理並簡要分析:spa
首先咱們定義一個接口:代理
public interface jdkProxy { public void test(String tString); }
以及它的實現類:code
public class jdkProxyImpl implements jdkProxy{ @Override public void test(String tString) { // TODO Auto-generated method stub
System.out.println("代理內方法"+tString); } }
接下來咱們要進行代理。代理過程分2步:對象
1.創建起代理對象和真實服務對象之間的關係,生產代理對象;blog
2.實現邏輯的代理;
在jdk動態代理中,要實現代理邏輯就必須實現InvocationHandler接口。它裏面定義了一個invoke方法,每當咱們經過代理對象調用方法時,它都會被轉發到這個invoke方法,咱們來
定義一個實現代理邏輯的類:
public class jdkProxyExample implements InvocationHandler{ //真實對象
private Object target = null; /** * 創建真實對象和代理對象的代理關係 * @param target真實對象 * @return 代理對象 */
public Object setTargetAndBind(Object target) { this.target = target; /** * 參數1:getClassLoader()提供類加載器;
參數2:getInterfaces()要掛載動態代理對象的接口,就是target的接口; */
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this); } /** * 代理方法邏輯 * @param:代理對象 * method:當前調度方法 * args:當前方法參數 * return 代理結果返回 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("進入代理對象方法,在此執行代理對象以前的一些操做"); //執行目標對象中的某個方法
Object object = method.invoke(target, args); System.out.println("調用代理對象方法以後的操做"); return object; } }
setTargetAndBind()這個方法內的newProxyInstance()方法經過傳入被代理內,再經過反射,生成一個代理類。
object obj = method.invoke(target,args),這個方法至關於調度真實對象的方法,只不過是經過反射區實現。它返回方法的執行結果。
而且在invoke方法裏,能夠在調用真實對象方法以前和以後作一些其餘的操做,這也是AOP的實現原理。
這樣,一個jdk動態代理就完成了,接下來能夠寫個測試類測試一下:
public class jdkProxyExampleTest { @Test public void testProxy() { jdkProxyExample jdkProxyExample = new jdkProxyExample(); //綁定關係,此時jdkProxy已是一個代理對象 jdkProxy jdkProxy = (jdkProxy)jdkProxyExample.setTargetAndBind(new jdkProxyImpl()); //執行代理對象方法 jdkProxy.test("動態代理jdk"); } }
打印結果以下:
1.咱們能夠看到,在綁定關係的方法中,實現被代理類的反射,須要咱們提供接口,而後它經過接口實現代理類。沒有它就找不到反射的方法。
2.因爲java的單繼承機制:首先jdk動態代理是經過newInstance動態的生成代理對象的,newInstance經過ProxyGenerator生成的字節碼錶明的類繼承了Proxy類:
public final class $Proxy0 extends Proxy implements jdkProxy{ ... }
$Proxy0這個類經過反編譯得到,它就是jdkProxy的實現類的動態的代理類。
因爲java的單繼承機制,被代理對象不能再被其餘的類繼承,那麼咱們若是想創建代理類和被代理類之間的關係,只能經過實現同一個接口了。