Java动态代理的两种实现方式详解【附相关jar文件下载】

 更新时间:2019年03月08日 11:21:24   作者:Bug开发攻城狮  
这篇文章主要介绍了Java动态代理的两种实现方式,结合实例形式分析了java动态代理的相关原理、实现方法与操作技巧,并附带相关jar文件供读者下载,需要的朋友可以参考下

本文实例讲述了Java动态代理的两种实现方式。分享给大家供大家参考,具体如下:

一说到动态代理,我们第一个想到肯定是大名鼎鼎的Spring AOP了。在AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。jdk动态代理是由java内部的反射机制来实现的,cglib动态代理是通过继承来实现的,底层则是借助asm(Java 字节码操控框架)来实现的(采用字节码的方式,给A类创建一个子类B,子类B使用方法拦截的技术拦截所以父类的方法调用)。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。。

公用的接口和实现类

public interface UserService {
  public String getName(int id);
  public Integer getAge(int id);
}
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;
  }
}

JDK的动态代理实现

jdk的动态代理,依赖的是反射包下的invocationHandler接口,我们的代理类实现invocationHandler,重写invoke()方法,每当我们的代理类调用方法时,都会默认先经过invoke()方法。

public class UserInvocationHandler implements InvocationHandler {
  private Object target;
  UserInvocationHandler() {
    super();
  }
  UserInvocationHandler(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;
    }
  }
}

测试类

public class M {
  public static void main(String[] args) {
    UserService userService = new UserServiceImpl();
    InvocationHandler invocationHandler = new UserInvocationHandler(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));
  }
}

测试效果

CGLIB的动态代理实现

cglib依赖的是cglib包下的methodInterceptor接口,每调用代理类的方法,都会调用intercept方法

public class CglibMethodInterceptor implements MethodInterceptor {
  @Override
  public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    System.out.println("------before " + methodProxy.getSuperName() + "------");
    Object o1 = methodProxy.invokeSuper(o, args);
    System.out.println("------after " + methodProxy.getSuperName() + "------");
    return o1;
  }
}

测试类

public class M {
  public static void main(String[] args) {
    CglibMethodInterceptor cglibProxy = new CglibMethodInterceptor();
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(UserServiceImpl.class);
    enhancer.setCallback(cglibProxy);
    UserService o = (UserService) enhancer.create();
    o.getName(1);
    o.getAge(1);
  }
}

测试结果

ps:cglib的动态代理,需要cglib.jarasm.jar支持

附:点击此处本站下载 cglib.jar  asm.jar

更多关于java算法相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。

相关文章

  • 带你深入了解java-代理机制

    带你深入了解java-代理机制

    Java 有两种代理方式,一种是静态代理,另一种是动态代理。如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理
    2021-08-08
  • 详解快速排序算法中的区间划分法及Java实现示例

    详解快速排序算法中的区间划分法及Java实现示例

    这篇文章主要介绍了详解快速排序算法中的区间划分法及Java实现示例,文中分别介绍了快排时两种区间划分的思路,需要的朋友可以参考下
    2016-04-04
  • SpringBoot+微信小程序实现文件上传与下载功能详解

    SpringBoot+微信小程序实现文件上传与下载功能详解

    这篇文章主要为大家介绍了SpringBoot整合微信小程序实现文件上传与下载功能,文中的实现步骤讲解详细,快跟随小编一起学习一下吧
    2022-03-03
  • Mybatis MapperScannerConfigurer自动扫描Mapper接口生成代理注入到Spring的方法

    Mybatis MapperScannerConfigurer自动扫描Mapper接口生成代理注入到Spring的方法

    这篇文章主要给大家介绍了关于Mybatis MapperScannerConfigurer自动扫描将Mapper接口生成代理注入到Spring的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2019-03-03
  • java简单网页抓取的实现方法

    java简单网页抓取的实现方法

    这篇文章主要介绍了java简单网页抓取的实现方法,详细分析了与Java网页抓取相关的tcp及URL相关概念,以及对应的类文件原理,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • Java swing五子棋的实现方法

    Java swing五子棋的实现方法

    这篇文章主要为大家详细介绍了Java swing五子棋的实现方法,Java开发图形界面程序五子棋的实现方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Java EasyExcel导入带图片的完整过程记录

    Java EasyExcel导入带图片的完整过程记录

    这篇文章主要介绍了关于结合EasyExcel和ApachePOI来实现Excel数据批量导入并读取图片的过程,文中通过图文以及代码介绍的非常详细,需要的朋友可以参考下
    2024-12-12
  • Spring+Junit4进行接口测试实例代码

    Spring+Junit4进行接口测试实例代码

    这篇文章主要介绍了Spring+Junit4进行接口测试实例代码,涉及pom.xml、bean的配置,以及接口测试代码等相关内容,小编觉得还是挺不错的,这里分享给大家,需要的朋友可以参考下
    2018-01-01
  • java实现五子棋大战

    java实现五子棋大战

    这篇文章主要为大家详细介绍了java实现五子棋大战,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  •  java中Thread.sleep()的具体使用

     java中Thread.sleep()的具体使用

    本文主要介绍了 java中Thread.sleep()的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04

最新评论