java反射兩種實(shí)現(xiàn)方式

反射是指在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為java語(yǔ)言的反射機(jī)制。Java中有兩種方式實(shí)現(xiàn)反射,接下來我們來一一分析一下。
1.通過java體系自帶的反射機(jī)制,首先我們來看一個(gè)例子。

  • 定義一個(gè)接口
public interface GoodService {

    String sayHello(String name);

}
  • 添加實(shí)現(xiàn)類

public class GoodServiceImpl implements GoodService {
    @Override
    public String sayHello(String name) {
        return name + " 你好";
    }
}
  • 定義動(dòng)態(tài)反射的代理類
public class ControllerProxy implements InvocationHandler {

    private GoodService goodService;

    public ControllerProxy(GoodService goodService) {
        this.goodService = goodService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object value = method.invoke(goodService,args);
        System.out.println("after");
        return value;
    }
}

  • 最后測(cè)試一下
public class GoodClient {


    /**
     *
     * @param args
     */
    public static void main(String[] args){

        GoodService goodService = new GoodServiceImpl();

        ControllerProxy proxy = new ControllerProxy(goodService);
        GoodService gs = (GoodService) Proxy.newProxyInstance(proxy.getClass().getClassLoader(),goodService.getClass().getInterfaces(),proxy);
        String dd = gs.sayHello("張三");
        System.out.println(dd);

 }

}

通過上面的列子可以發(fā)現(xiàn),如果我們需要對(duì)接口進(jìn)行擴(kuò)展則無(wú)須對(duì)源碼進(jìn)行修改,只需對(duì)代理類進(jìn)行擴(kuò)展即可達(dá)到目的,所以反射機(jī)制提供了一種對(duì)Java擴(kuò)展的方式,這種方式無(wú)侵入性。但是這種方式也不是十全十美,也有自己的瓶頸,首先被代理的只能是接口,這樣就限制了使用范圍,其次是性能問題,通過反射獲取對(duì)象的屬性的值要遠(yuǎn)比直接通過屬性取值,最后反射的應(yīng)用會(huì)模糊應(yīng)用內(nèi)實(shí)際要發(fā)生的事。
2.除了java自帶的反射機(jī)制外,另一種實(shí)現(xiàn)方式就是cglib,cglib完全避開了java自帶的反射機(jī)制帶來的問題,cglib不僅僅可以代理接口,同時(shí)可以給普通類進(jìn)行代理,同時(shí)它采用fastclass機(jī)制為代理類和被代理類各生成一個(gè)Class,這個(gè)Class會(huì)為代理類或被代理類的方法分配一個(gè)index(int類型)。
這個(gè)index當(dāng)做一個(gè)入?yún)?,F(xiàn)astClass就可以直接定位要調(diào)用的方法直接進(jìn)行調(diào)用,這樣省去了反射調(diào)用,所以調(diào)用效率比JDK動(dòng)態(tài)代理通過反射調(diào)用高。接下來我們擼段代碼來看看

  • 直接定義cglib代理類
public class MethodInterProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before");
        Object obj = methodProxy.invokeSuper(o, objects);
        System.out.println("after");
        return  obj;
    }
}
  • 實(shí)現(xiàn)類直接采用上面的實(shí)現(xiàn)類
  • 運(yùn)行結(jié)果
public class GoodClient {


    /**
     *
     * @param args
     */
    public static void main(String[] args){

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(GoodServiceImpl.class);
        MethodInterProxy mproxy = new MethodInterProxy();
        enhancer.setCallbacks(new Callback[]{NoOp.INSTANCE,mproxy});
        enhancer.setCallbackFilter(new MethodFilter());
        GoodService gsd = (GoodService) enhancer.create();
        String ds = gsd.sayHello("DE");
        System.out.println(ds);

    }

}

通過上面的例子可以看到cglib直接對(duì)實(shí)現(xiàn)類進(jìn)行代理,cglib底層采用ASM進(jìn)行字節(jié)碼生成,這種方式遠(yuǎn)比jdk自帶的反射機(jī)制要復(fù)雜。
最后兩者進(jìn)行對(duì)比
1.JDK動(dòng)態(tài)代理是實(shí)現(xiàn)了被代理對(duì)象的接口,Cglib是繼承了被代理對(duì)象。
2.JDK和Cglib都是在運(yùn)行期生成字節(jié)碼,JDK是直接寫Class字節(jié)碼,Cglib使用ASM框架寫Class字節(jié)碼,Cglib代理實(shí)現(xiàn)更復(fù)雜,生成代理類比JDK效率低。
3.JDK調(diào)用代理方法,是通過反射機(jī)制調(diào)用,Cglib是通過FastClass機(jī)制直接調(diào)用方法,Cglib執(zhí)行效率更高。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在一個(gè)方法內(nèi)部定義的變量都存儲(chǔ)在棧中,當(dāng)這個(gè)函數(shù)運(yùn)行結(jié)束后,其對(duì)應(yīng)的棧就會(huì)被回收,此時(shí),在其方法體中定義的變量將不...
    Y了個(gè)J閱讀 4,576評(píng)論 1 14
  • Java設(shè)計(jì)模式——代理模式 代理模式主要分為接口,委托類,代理類 接口:規(guī)定具體方法委托類:實(shí)現(xiàn)接口,完成具體的...
    vczyh閱讀 735評(píng)論 0 0
  • 過年,是中華民族幾千年傳統(tǒng)的最大節(jié)日。最喜慶、最歡樂、最熱鬧,讓人留戀難忘,回味無(wú)窮。 古代相傳,有一種叫做“夕"...
    思索_a621閱讀 318評(píng)論 0 1
  • 幸福并不復(fù)雜。餓時(shí),飯是幸福,夠飽即可;渴時(shí),水是幸福,夠飲即可;裸時(shí),衣是幸福,夠穿即可;窮時(shí),錢是幸福,夠用即...
    金豆小糊涂閱讀 384評(píng)論 0 1
  • 睡不著,發(fā)下牢騷 今天健身完回來, 你許久未見的朋友 過來找你 剛到家,約見面 我滿身汗,鍛煉的也累 說不去了,你...
    皮諾曹73閱讀 257評(píng)論 0 0

友情鏈接更多精彩內(nèi)容