日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java动态代理的两种实现方法

發布時間:2024/2/28 java 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java动态代理的两种实现方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自?http://blog.csdn.net/HEYUTAO007/article/details/49738887

?AOP的攔截功能是由java中的動態代理來實現的。說白了,就是在目標類的基礎上增加切面邏輯,生成增強的目標類(該切面邏輯或者在目標類函數執行之前,或者目標類函數執行之后,或者在目標類函數拋出異常時候執行。不同的切入時機對應不同的Interceptor的種類,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。


那么動態代理是如何實現將切面邏輯(advise)織入到目標類方法中去的呢?下面我們就來詳細介紹并實現AOP中用到的兩種動態代理。

AOP的源碼中用到了兩種動態代理來實現攔截切入功能:jdk動態代理和cglib動態代理。兩種方法同時存在,各有優劣。jdk動態代理是由java內部的反射機制來實現的,cglib動態代理底層則是借助asm來實現的。總的來說,反射機制在生成類的過程中比較高效,而asm在生成類之后的相關執行過程中比較高效(可以通過將asm生成的類進行緩存,這樣解決asm生成類過程低效問題)。還有一點必須注意:jdk動態代理的應用前提,必須是目標類基于統一的接口。如果沒有上述前提,jdk動態代理不能應用。由此可以看出,jdk動態代理有一定的局限性,cglib這種第三方類庫實現的動態代理應用更加廣泛,且在效率上更有優勢。。

1、定義接口和實現

[java]?view plain?copy
  • package?com.meituan.hyt.test3.service;??
  • ??
  • ??
  • public?interface?UserService?{??
  • ????public?String?getName(int?id);??
  • ??
  • ????public?Integer?getAge(int?id);??
  • }??

  • [java]?view plain?copy
  • package?com.meituan.hyt.test3.service.impl;??
  • ??
  • import?com.meituan.hyt.test3.service.UserService;??
  • ??
  • ??
  • public?class?UserServiceImpl?implements?UserService?{??
  • ????@Override??
  • ????public?String?getName(int?id)?{??
  • ????????System.out.println("------getName------");??
  • ????????return?"Tom";??
  • ????}??
  • ??
  • ????@Override??
  • ????public?Integer?getAge(int?id)?{??
  • ????????System.out.println("------getAge------");??
  • ????????return?10;??
  • ????}??
  • }??

  • 2、jdk動態代理實現

    [java]?view plain?copy
  • package?com.meituan.hyt.test3.jdk;??
  • ??
  • import?java.lang.reflect.InvocationHandler;??
  • import?java.lang.reflect.Method;??
  • ??
  • ??
  • public?class?MyInvocationHandler?implements?InvocationHandler?{??
  • ????private?Object?target;??
  • ??
  • ????MyInvocationHandler()?{??
  • ????????super();??
  • ????}??
  • ??
  • ????MyInvocationHandler(Object?target)?{??
  • ????????super();??
  • ????????this.target?=?target;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?Object?invoke(Object?o,?Method?method,?Object[]?args)?throws?Throwable?{??
  • ????????if("getName".equals(method.getName())){??
  • ????????????System.out.println("++++++before?"?+?method.getName()?+?"++++++");??
  • ????????????Object?result?=?method.invoke(target,?args);??
  • ????????????System.out.println("++++++after?"?+?method.getName()?+?"++++++");??
  • ????????????return?result;??
  • ????????}else{??
  • ????????????Object?result?=?method.invoke(target,?args);??
  • ????????????return?result;??
  • ????????}??
  • ??
  • ????}??
  • }??

  • [java]?view plain?copy
  • package?com.meituan.hyt.test3.jdk;??
  • ??
  • import?com.meituan.hyt.test3.service.UserService;??
  • import?com.meituan.hyt.test3.service.impl.UserServiceImpl;??
  • ??
  • import?java.lang.reflect.InvocationHandler;??
  • import?java.lang.reflect.Proxy;??
  • ??
  • ??
  • public?class?Main1?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????UserService?userService?=?new?UserServiceImpl();??
  • ????????InvocationHandler?invocationHandler?=?new?MyInvocationHandler(userService);??
  • ????????UserService?userServiceProxy?=?(UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(),??
  • ????????????????userService.getClass().getInterfaces(),?invocationHandler);??
  • ????????System.out.println(userServiceProxy.getName(1));??
  • ????????System.out.println(userServiceProxy.getAge(1));??
  • ????}??
  • }??

  • 運行結果

    ++++++before getName++++++
    ------getName------
    ++++++after getName++++++
    Tom
    ------getAge------
    10

    3、cglib動態代理實現

    Cglib是一個優秀的動態代理框架,它的底層使用ASM在內存中動態的生成被代理類的子類,使用CGLIB即使代理類沒有實現任何接口也可以實現動態代理功能。CGLIB具有簡單易用,它的運行速度要遠遠快于JDK的Proxy動態代理:

    CGLIB的核心類:
    ??? net.sf.cglib.proxy.Enhancer – 主要的增強類
    ??? net.sf.cglib.proxy.MethodInterceptor – 主要的方法攔截類,它是Callback接口的子接口,需要用戶實現
    ??? net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method類的代理類,可以方便的實現對源對象方法的調用,如使用:
    ??? Object o = methodProxy.invokeSuper(proxy, args);//雖然第一個參數是被代理對象,也不會出現死循環的問題。

    net.sf.cglib.proxy.MethodInterceptor接口是最通用的回調(callback)類型,它經常被基于代理的AOP用來實現攔截(intercept)方法的調用。這個接口只定義了一個方法
    public Object intercept(Object object, java.lang.reflect.Method method,
    Object[] args, MethodProxy proxy) throws Throwable;

    第一個參數是代理對像,第二和第三個參數分別是攔截的方法和方法的參數。原來的方法可能通過使用java.lang.reflect.Method對象的一般反射調用,或者使用 net.sf.cglib.proxy.MethodProxy對象調用。net.sf.cglib.proxy.MethodProxy通常被首選使用,因為它更快。

    [java]?view plain?copy
  • package?com.meituan.hyt.test3.cglib;??
  • ??
  • ??
  • import?net.sf.cglib.proxy.MethodInterceptor;??
  • import?net.sf.cglib.proxy.MethodProxy;??
  • ??
  • import?java.lang.reflect.Method;??
  • ??
  • ??
  • public?class?CglibProxy?implements?MethodInterceptor?{??
  • ????@Override??
  • ????public?Object?intercept(Object?o,?Method?method,?Object[]?args,?MethodProxy?methodProxy)?throws?Throwable?{??
  • ????????System.out.println("++++++before?"?+?methodProxy.getSuperName()?+?"++++++");??
  • ????????System.out.println(method.getName());??
  • ????????Object?o1?=?methodProxy.invokeSuper(o,?args);??
  • ????????System.out.println("++++++before?"?+?methodProxy.getSuperName()?+?"++++++");??
  • ????????return?o1;??
  • ????}??
  • }??


  • [java]?view plain?copy
  • package?com.meituan.hyt.test3.cglib;??
  • ??
  • import?com.meituan.hyt.test3.service.UserService;??
  • import?com.meituan.hyt.test3.service.impl.UserServiceImpl;??
  • import?net.sf.cglib.proxy.Enhancer;??
  • ??
  • ??
  • ??
  • public?class?Main2?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????CglibProxy?cglibProxy?=?new?CglibProxy();??
  • ??
  • ????????Enhancer?enhancer?=?new?Enhancer();??
  • ????????enhancer.setSuperclass(UserServiceImpl.class);??
  • ????????enhancer.setCallback(cglibProxy);??
  • ??
  • ????????UserService?o?=?(UserService)enhancer.create();??
  • ????????o.getName(1);??
  • ????????o.getAge(1);??
  • ????}??
  • }??

  • 運行結果:

    ++++++before CGLIB$getName$0++++++
    getName
    ------getName------
    ++++++before CGLIB$getName$0++++++
    ++++++before CGLIB$getAge$1++++++
    getAge
    ------getAge------
    ++++++before CGLIB$getAge$1++++++


    總結

    以上是生活随笔為你收集整理的Java动态代理的两种实现方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。