Spring学习之动态代理(JDK动态代理和CGLIB动态代理)

前言

动态代理,是一种通过运行时操作字节码,以达到增强类的功能的技术,也是Spring AOP操作的基础,关于AOP的内容,将在后面的笔记中详细讲解,本小节主要是理清楚动态代理,毕竟,Spring的AOP是基于动态代理技术,对动态代理技术有所了解,对于学习Spring AOP也会有帮助

动态代理技术详解

动态代理,现在主要是用于增强类的功能,同时由于是具有动态性,所以避免了需要频繁创建类的操作,同时,也使得原有的代码在不需要改变的情况下,对类的功能进行增强,主要的动态代理技术有:通过实现目标接口,重写其方法,以增强其能力,典型的以JDK动态代理为代表;或者,通过继承类,重写其方法以增强其能力,典型的以CGLib为代表,这两种技术分别从不同的方向来对类的能力进行扩充,接下来来具体看下这两种技术的特点以及差异。

基于JDK动态代理

基于JDK的动态代理技术,其主要特点就是目标类,也就是需要被代理的类,必须有接口,并且代理类必须实现跟它一样的接口,从而来起到代理其事务的功能,具体使用如下代码所示,假设有一个UserService类,主要用于负责用户的登录和退出,同时,有个日志类,负责记录用户的操作信息,直接将信息日志写在对应的UserService实现类中,可以达到目的,但显然这种方式不是很合理,特别是在UserService有很多个方法需要做日志记录的时候,就会使得日志记录代码遍布整个UserService,不仅使得代码的冗余很大,而且当需要进行修改的时候,也需要逐个修改,非常麻烦,这个时候,采用动态代理技术就是一种非常好的方法了。

/**
 * UserService接口
 */
interface UserService{

  void login();
  void logout();
}

/**
 * UseService实现类
 */
class UserServiceImpl implements UserService{

  @Override
  public void login() {
    System.out.println("someone login....");
  }

  @Override
  public void logout() {
    System.out.println("someone logout....");
  }
}

/**
 * 实现InvocationHandle接口,用于织入所要增强的代码
 */
class UserServiceHandle implements InvocationHandler{

  private UserService userService;

  public UserServiceHandle(UserService userService) {
    this.userService = userService;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    LogService.info();
    Object object = method.invoke(userService, args);
    LogService.info();
    return object;
  }
}

/**
 * 代理类工厂,用于产生UseService类的代理类
 */
class ProxyFactory{

  public static UserService getProxyObject(UserService userService){

    // 使用JDK动态代理技术来创建对应的代理类
    return (UserService) Proxy.newProxyInstance(
        userService.getClass().getClassLoader(),
        userService.getClass().getInterfaces(),
        new UserServiceHandle(userService)
    );
  }
}

这样,当我们需要使用UseService类的时候,只需要从ProxyFactory中获取即可,而且获取的对象是UserService对象的代理类,也就是说,获得的对象是UserService对象的增强版

基于CGLib的动态代理技术

从上面的ProxyFactory工厂中可以看到,在使用JDK进行创建动态代理对象的时候,需要为其提供接口,或者说,如果所要增强的目标类没有实现任何接口,则JDK动态代理技术是无法为其创建对应的代理对象的,这是JDK动态代理技术的一种缺点,而CGLib动态代理技术则恰好弥补了这个缺点,CGLib动态代理技术使用的是继承该类的方式,从而避免了需要接口的缺陷,具体使用如下所示,注意,需要导入对应的依赖文件

/**
 * 基于CGLib的动态代理技术
 * 注意这里需要实现MethodInterceptor接口
 */
class ProxyFactory implements MethodInterceptor{

  // 提供对应的增强操作类
  private Enhancer enhancer = new Enhancer();

  public UserService getProxyObject(Class clazz){
    // 设置所要增强的类的父类
    enhancer.setSuperclass(clazz);
    // 设置回调对象
    enhancer.setCallback(this);
    // 创建对应的对象
    return (UserService) enhancer.create();
  }

  // 实现拦截方法,用于拦截对应的方法,并且对对应的方法进行增强
  // 参数含义:传入的对象, Method对象,方法的参数,进行代理后的Method对象
  @Override
  public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

    LogService.info();
    // 这里需要注意,由于methodProxy对象是增强后的Method对象,所以这里需要调用的
    // 是methodProxy父类的方法,也就是所以增强的类的方法,以实现原来的功能
    Object object = methodProxy.invokeSuper(o, objects);
    LogService.info();
    return object;
  }
}

可以看到,使用CGLib动态代理技术可以在不需要实现接口的情况下东塔为对象创建代理对象,在很大程度上弥补了JDK动态代理技术的缺点,不过由于CGLib动态代理技术是采用继承目标类的方式,所以也存在一些问题,比如说,对于final以及private修饰的方法是无法为其增强的,这里还需要注意一下。

总结

动态代理技术是实现AOP技术的基础,也是一种很方便地实现方式,常用的动态代理技术有基于JDK动态代理技术以及基于CGLib的动态代理技术,两种技术各有千秋,也都各有缺点基于JDK的动态代理技术需要为其提供接口,基于CGLib的动态代理技术不能为final以及private修饰的方法进行增强,在使用的时候需要根据具体进行进行合理选择。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • spring基础概念AOP与动态代理理解

    一.代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为"代理",所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 以简单模拟事务的执行过程说明各种代理区别 1.1 静态代理 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. public interface PersonDao { vo

  • spring cglib 与 jdk 动态代理

    1. 概述 JDK动态代理是利用java反射机制 生成一个实现接口的匿名类, 在调用具体方法前调用InvocationHandler来处理 Cglib动态代理是 利用asm开源包 把被代理类的class文件加载进来 通过修改其字节码生成子类来处理 如果目标对象实现了接口 那么默认使用jdk代理(可以强制使用cglib代理) 如果没有实现接口 必须使用cglib代理 强制使用cglib代理需要 *引入cglibjar包 *配置spring <aop:aspectj-autoproxy proxy-

  • 利用spring aop实现动态代理

    下面由我来给大家展示用spring aop实现动态代理的例子(电脑打印) 下面就看一下具体的代码: 先定义一个打印机的接口 package aop007_ComPrint; public interface Print { public void ColorPrint(); //彩色打印 public void WhitePrint(); //黑白打印 } 然后定义两个实现类,分别实现彩色打印和黑白打印 package aop007_ComPrint; public class ColorPri

  • 详解Spring的两种代理方式:JDK动态代理和CGLIB动态代理

    代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为"代理",所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用 A. 抽象主题角色 声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以是使用代理主题 B. 代理主题(Proxy)角色: 代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象:代理主题角

  • 浅谈Java代理(jdk静态代理、动态代理和cglib动态代理)

    一.代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强.加入一些非业务性代码,比如事务.日志.报警发邮件等操作. 二.jdk静态代理 1.业务接口 /** * 业务接口 * @author pc * */ public interface UserService { // 增加一个用户 public void addUser(); // 编辑账户 public void editUser(); } 2.业务实现类 /** * 业务实现类 * @author pc

  • java动态代理和cglib动态代理示例分享

    java动态代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. 动态代理:在程序运行时,运用反射机制动态创建而成. 一.首先我们进行java动态代理的演示. 现在我们有一个简单的业务接口Saying,如下: 复制代码 代码如下: package testAOP;public interface Saying {public void sayHello(String name);    public void ta

  • jdk动态代理和cglib动态代理详解

    目录 静态代理 基于继承的方式实现静态代理 基于聚合的方式实现静态代理 继承与聚合方式实现的静态代理对比 动态代理 JDK动态代理 如何实现一个HashMap的动态代理类? Cglib动态代理 JDK与Cglib动态代理对比? 动态代理和静态代理的区别? Spring如何选择两种代理模式的? 总结 如上图,代理模式可分为动态代理和静态代理,我们比较常用的有动态代理中的jdk动态代理和Cglib代理,像spring框架.hibernate框架中都采用了JDK动态代理,下面将结合代码阐述两种代理模式

  • Spring学习之动态代理(JDK动态代理和CGLIB动态代理)

    前言 动态代理,是一种通过运行时操作字节码,以达到增强类的功能的技术,也是Spring AOP操作的基础,关于AOP的内容,将在后面的笔记中详细讲解,本小节主要是理清楚动态代理,毕竟,Spring的AOP是基于动态代理技术,对动态代理技术有所了解,对于学习Spring AOP也会有帮助 动态代理技术详解 动态代理,现在主要是用于增强类的功能,同时由于是具有动态性,所以避免了需要频繁创建类的操作,同时,也使得原有的代码在不需要改变的情况下,对类的功能进行增强,主要的动态代理技术有:通过实现目标接口

  • Aop动态代理和cglib实现代码详解

    一般我们使用Aop对象时,常用动态代理模式,即是采用映射一个相同的类在此基础上进行前置后置操作. 动态代理多是采用原类实现父类接口,然后动态代理一个和原类相同的双胞胎兄弟类来实现映射. 父类 public interface InterF { public void save(); } 需要映射的类 public class Origin implements InterF{ @Override public void save() { System.out.println("测试一下"

  • Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理,另一种是CGLib的方式. 自Java 1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,后来这项技术被用到了Spring的很多地方. JDK动态代理主要涉及java.lang.reflect包下边的两个类:Proxy和InvocationHandler.其中,Invoc

  • Java代理模式实例详解【静态代理与动态代理】

    本文实例讲述了Java代理模式.分享给大家供大家参考,具体如下: 即Proxy Pattern,23种java常用设计模式之一.代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问. Java的代理模式是Java中比较常用的设计模式,分为2中代理:静态代理与动态代理(JDK动态代理和cglib动态代理) 优点: 职责清晰 真实角色只需关注业务逻辑的实现,非业务逻辑部分,后期通过代理类完成即可. 高扩展性 不管真实角色如何变化,由于接口是固定的,代理类无需做任何改动. 缺点: 很明显的一点

  • 解析动态代理jdk的Proxy与spring的CGlib(包括区别介绍)

    目录 1. 为什么要使用动态代理? 2.JDK Proxy 动态代理面向接口的动态代理 3.CGlib动态代理 原理区别: 两个动态代理的区别 1. 为什么要使用动态代理? 动态代理:在不改变原有代码的情况下上进行对象功能增强 使用代理对象代替原来的对象完成功能 进而达到拓展功能的目的 2.JDK Proxy 动态代理面向接口的动态代理 特点: 一定要有接口和实现类的存在 代理对象增强的是实现类 在实现接口的方法重写的方法 生成的代理对象只能转换成 接口的不能转换成 被代理类 代理对象只能增强接

  • java动态代理(jdk与cglib)详细解析

    JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经

随机推荐