老生常谈设计模式之动态代理

一、动态代理概念

动态代理分为JDK动态代理和cglib动态代理两种方式。

jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。

总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。

还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。

由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。

二、JDK动态代理

以下代码使用代理模式实现一个大小写字符转换的功能。

定义接口和实现类:

ISomeService接口:

package com.ietree.basicskill.designpattern.dynamicproxy.jdk;

/**
 * 接口类
 *
 * @author Root
 */
public interface ISomeService {

  String doFirst();

  void doSecond();
}

SomeServiceImpl实现类:

package com.ietree.basicskill.designpattern.dynamicproxy.jdk;

/**
 * 实现类
 *
 * @author Root
 */
public class SomeServiceImpl implements ISomeService {

  @Override
  public String doFirst() {
    System.out.println("执行doFirst()...");
    String result = "abcde";
    return result;
  }

  @Override
  public void doSecond() {
    System.out.println("执行doSecond()...");
  }

}

JDK动态代理类:

package com.ietree.basicskill.designpattern.dynamicproxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Main {
  public static void main(String[] args) {

    final ISomeService target = new SomeServiceImpl();

    // 使用JDK的Proxy动态代理,要求目标类和代理类必须实现相同的接口,因为其底层的执行原理与静态代理的相同
    ISomeService service = (ISomeService) Proxy.newProxyInstance(
        // 目标类的类加载器
        target.getClass().getClassLoader(),
        // 目标类所实现的所有接口
        target.getClass().getInterfaces(),
        new InvocationHandler() {
          // proxy:代理对象
          // method:目标方法
          // args:目标方法的参数列表
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 调用目标方法
            Object result = method.invoke(target, args);
            if (result != null) {
              result = ((String) result).toUpperCase();
            }
            return result;
          }
        });
    String result = service.doFirst();
    System.out.println(result);

    service.doSecond();
  }
}

三、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通常被首选使用,因为它更快。

以下程序实现了大小写转换的功能:

实现类SomeService:

package com.ietree.basicskill.designpattern.dynamicproxy.cglib;

/**
 * 实现类
 *
 * @author Root
 */
public class SomeService {

  public String doFirst() {
    System.out.println("执行doFirst()...");
    String result = "abcde";
    return result;
  }

  public void doSecond() {
    System.out.println("执行doSecond()...");
  }

}

代理类MyCglibFactory:

package com.ietree.basicskill.designpattern.dynamicproxy.cglib;

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 MyCglibFactory implements MethodInterceptor {

  private SomeService target;

  public MyCglibFactory() {
    super();
    target = new SomeService();
  }

  public SomeService myCglibCreator() {
    // 创建增强器对象
    Enhancer enhancer = new Enhancer();
    // 指定目标类,即父类
    enhancer.setSuperclass(SomeService.class);
    // 设置回调接口对象
    enhancer.setCallback(this);

    return (SomeService) enhancer.create();
  }

  @Override
  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    // 调用目标方法
    Object result = method.invoke(target, args);
    if (result != null) {
      result = ((String) result).toUpperCase();
    }
    return result;
  }

}

测试:

package com.ietree.basicskill.designpattern.dynamicproxy.cglib;

public class Main {
  public static void main(String[] args) {

    SomeService service = new MyCglibFactory().myCglibCreator();

    String result = service.doFirst();
    System.out.println("result = " + result);

    service.doSecond();
  }
}

运行结果:

执行doFirst()...
result = ABCDE
执行doSecond()...

以上这篇老生常谈设计模式之动态代理就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • java 代理模式及动态代理机制深入分析

    java 代理模式及动态代理机制深入分析 代理设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式一般涉及到的角色有: 抽象角色:声明真实对象和代理对象的共同接口: 代理角色:代理对象角色内

  • Java动态代理分析及理解

    Java动态代理分析及理解 代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Subject { public void doSomething(); } public class RealSubject implements Subject { public void doSomething() { System.out.println( "call

  • java 反射和动态代理详解及实例代码

    一.java中的反射 1.通过反射加载类的属性和方法实例代码: /** * java.lang.Class 是反射的源头 * 我们创建了一个类,通过编译(javac.exe)生成对应的class文件,之后我们通过java.exe加载(jvm的类加载器加载)此class文件 * 此class文件加载到内存后,就是一个运行时类,存在缓存区,这个运行时类本事就是一个Class的实例 * 每一个运行时类只加载一次, */ Class<StudentExam> clazz = StudentExam.c

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

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

  • 详解java动态代理模式

    本文针对java动态代理进行知识点整理,具体内容如下 一. JAVA的动态代理(比较官方说法) 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处 理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的 对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提 供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工

  • Java动态代理分析及简单实例

      Java动态代理 要想了解Java动态代理,首先要了解什么叫做代理,熟悉设计模式的朋友一定知道在Gof总结的23种设计模式中,有一种叫做代理(Proxy)的对象结构型模式,动态代理中的代理,指的就是这种设计模式. 在我看来所谓的代理模式,和23种设计模式中的"装饰模式"是一个东西.23种设计模式中将它们作为两种模式,网上也有些文章讲这两种模式的异同,从细节来看,确实可以人为地区分这两种模式,但是抽象到一定高度后,我认为这两种模式是完全一样的.因此学会了代理模式,也就同时掌握了装饰模

  • 老生常谈设计模式之动态代理

    一.动态代理概念 动态代理分为JDK动态代理和cglib动态代理两种方式. jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的. 总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题). 还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口.如果没有上述前提,jdk动态代理不能应用. 由此可以看出,jdk动态代理有一定的局限性,cg

  • Java设计模式之动态代理模式实例分析

    本文实例讲述了Java设计模式之动态代理模式.分享给大家供大家参考,具体如下: 前面介绍了静态代理模式,动态代理比静态代理模式更加强大.它能在程序运行时动态的生成代理对象.所谓动态代理类是在运行时生成的class,在生成它时,你必须提供一组interface给它,则动态代理类就宣称它实现了这些interface.当然,动态代理类就充当一个代理,你不要企图它会帮你干实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作. 动态代理的角色和静态代理的角色一样: ① 抽象角色:

  • Java设计模式之动态代理

    动态代理的意义在于生成一个占位(又称代理对象),来代理真实对象,从而控制真实对象的访问. 我们首先来谈谈什么是代理模式.假设客户带着需求去找公司,显然不会直接和软件工程师谈,而是和商务谈,此时客户会认为商务就代表公司,客户是通过商务去访问软件工程师的.我们就可以认为商务(代理对象)代理了软件工程师(真实对象),因此,代理的作用就是,在真实对象访问之前或者之后加入对应的逻辑,或者根据其他规则控制是否使用真实对象. 商务和软件工程师是代理和被代理的关系,客户是通过商务去访问软件工程师的.此时客户就是

  • Java设计模式之静态代理模式实例分析

    本文实例讲述了Java设计模式之静态代理模式.分享给大家供大家参考,具体如下: 代理模式,可以通过代理可以在原来的基础上附加一些其他的操作.静态代理模式相对比较简单无需再程序运行时动态的进行代理. 静态代理模式的角色: ① 抽象角色:真实对象和代理对象的共同接口.其中声明真实对象和代理对象需要做的事. ② 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用. ③ 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作. 下面提

  • Java动态代理之拦截器的应用

    由于动态代理一般都比较难理解,程序设计者会设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法.含义和作用即可,无须知道动态代理是怎么实现的.用JDK动态代理来实现一个拦截器的逻辑,为此先定义拦截器接口Interceptor,如下所示: /** * @Auther: haozz * @Date: 2018/5/27 22:15 * @Description:拦截器接口 **/ public interface Interceptor { boolean before(Object pr

  • Java动态代理(设计模式)代码详解

    基础:需要具备面向对象设计思想,多态的思想,反射的思想: Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.通过阅读本文,读者将会对Java动态代理机制有更加深入的理解.本文首先从Java动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内部实现. 代理模

  • Java JDK动态代理(AOP)的实现原理与使用详析

    本文主要给大家介绍了关于Java JDK动态代理(AOP)实现原理与使用的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 一.什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 代理模式UML图: 简单结构示意图: 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对

随机推荐