JDK動態代理與CGLib動態代理

JDK動態代理:

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動態代理:

CGLib採用了很是底層的字節碼技術,其原理是經過字節碼技術爲一個類建立子類,並在子類中採用方法攔截的技術攔截全部分類方法的調用,順勢織入和橫切邏輯。-http://blog.csdn.net/yakoo5/article/details/9099133/代理

 

點擊下載編寫CGlib動態代理測試所需jar包code

 

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類是沒法進行代理的。

相關文章
相關標籤/搜索