iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >JAVA如何实现动态代理技术
  • 225
分享到

JAVA如何实现动态代理技术

java 2023-05-30 22:05:14 225人浏览 薄情痞子
摘要

这篇文章主要为大家展示了“JAVA如何实现动态代理技术”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JAVA如何实现动态代理技术”这篇文章吧。一、引出动态代理生活中代理应该是很常见的,比如你可以

这篇文章主要为大家展示了“JAVA如何实现动态代理技术”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JAVA如何实现动态代理技术”这篇文章吧。

一、引出动态代理

生活中代理应该是很常见的,比如你可以通过代理商去买电脑,也可以直接找厂商买电脑,最终都是买到了电脑。程序中也一样存在代理的情况,比如要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常处理、日志、计算方法耗时等等,那么我们会怎么做呢?

会编写一个与目标类拥有相同接口的代理类,代理类的每个方法调用目标类的相同方法,然后在调用方法前后加上系统功能所需要的代码。

如果采用工厂模式或者配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换。

样例如下:

public class X{ public void sayHello(){ syso:say hello; }}

现在我要在这个方法之前添加一个时间,方法之后添加一个时间,计算这个方法执行的时间一共是多少.如果我没有得到sayHello源码,那么我怎么做呢?写一个代理:

public class XProxy{ private X x; public void sayHello {   startTime:  x.syHello();  endTime; }}

说明:上面的是伪代码。

把开始时间和结束时间放在这个方法的前后就可以了.
通常我们让两个方法实现同一个接口.那么client想用X也可以,想用XProxy也可以了.具体的原理图,如下图所示:

JAVA如何实现动态代理技术

二、创建动态代理类

现在试想一下,上面只是代理了一个目标类,如果多个目标类,那么是不是要创建N多个代理类呢?那样不是代码太不灵活且笨重了。当然不会。

java虚拟机可以在运行期间动态生成类,这种类是以字节码的形式生成出来的。这种动态生成的类往往呢就是代理类。即动态代理类。

JVM生成的动态代理类必须满足一定的条件,这就是必须实现一个或多个接口。所以JVM生成的动态代理只能用作具有相同接口的目标类的代理。(动态生成的类不是代理,我们只是吧这个类当成代理来用。)

Proxy动态代理的api

JAVA如何实现动态代理技术

两个参数应该很容易理解:

第一个参数:我们知道任何一个字节码都是需要通过类加载器来加载的,那么这个动态生成的字节码也不例外,需要给它一个类加载器。

第二个参数:就是动态代理类生成,必须满足的一个条件,需要实现一个或者多个接口,否则这个生成的类字节码中就没有方法了,没有方法就失去了其功能意义。

下面我们动手来创建一个动态的代理类,大体思路为:

创建实现Collection接口的动态类和查看其名称,分析Proxy.getProxyClass方法的各个参数

编码列出动态类中的所有构造方法和参数签名

编码列出动态类中的所有方法和参数签名

创建动态类的实例对象:1)用反射获取构造方法   2)编写一个最简单的invocationHandle类   3)调用构造方法创建动态类的实例对象,并将编写的InvocationHandle类的实例对象传递进去   4)打印创建对象和调用对象的没有返回的方法和getClass方法,演示调用其他有返回值方法报告了异常。

5)将创建动态类的实例对象的代理写成匿名内部类方式,简化代码。

样例分步实现如下:

(1)首先我们来完成前面3步:

package study.javaenhance;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Collection;public class ProxyTest{ public static void main(String[] args)  {  Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);  System.out.println(clazzProxy1.getName());    //上面输出的为一个类,那么一个类肯定有其构造方法和方法,下面我们来列出来    System.out.println("----------begin constructors list----------");  //1.列出构造方法  Constructor[] constructors = clazzProxy1.getConstructors();  for (Constructor constructor : constructors)   {   String name = constructor.getName();   StringBuilder sBuilder = new StringBuilder(name);   sBuilder.append('(');   Class[] clazzParams = constructor.getParameterTypes();   for (Class clazzParam : clazzParams) {    sBuilder.append(clazzParam.getName()).append(',');   }   if(clazzParams!=null && clazzParams.length != 0)    sBuilder.deleteCharAt(sBuilder.length()-1);   sBuilder.append(')');   System.out.println(sBuilder.toString());   }    //2.列出这个类字节码中的所有方法  System.out.println("----------begin methods list----------");  Method[] methods = clazzProxy1.getMethods();  for(Method method : methods){   String name = method.getName();   StringBuilder sBuilder = new StringBuilder(name);   sBuilder.append('(');   Class[] clazzParams = method.getParameterTypes();   for(Class clazzParam : clazzParams){    sBuilder.append(clazzParam.getName()).append(',');   }   if(clazzParams!=null && clazzParams.length != 0)    sBuilder.deleteCharAt(sBuilder.length()-1);   sBuilder.append(')');   System.out.println(sBuilder.toString());     }     }}

输出结果如下:

$Proxy0
----------begin constructors list----------
$Proxy0(java.lang.reflect.InvocationHandler)
----------begin methods list----------
add(java.lang.Object)
hashCode()
clear()
equals(java.lang.Object)
toString()
contains(java.lang.Object)
isEmpty()
addAll(java.util.Collection)
iterator()
size()
toArray([Ljava.lang.Object;)
toArray()
remove(java.lang.Object)
containsAll(java.util.Collection)
removeAll(java.util.Collection)
retainAll(java.util.Collection)
isProxyClass(java.lang.Class)
getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)
getInvocationHandler(java.lang.Object)
newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)
wait()
wait(long,int)
wait(long)
getClass()
notify()
notifyAll()

可以看到所有的方法均是来自Collection 和父类Object中的方法,符合我们的预期结果。接下来我们进入第四步和第五步的实现:

首先,我们来创建这个动态代理类的实例。那么直接clazzProxy1.newInstance();可不可以呢?显然是不可以的嘛.我们刚刚说了,动态生成的这个代理类只有一个构造方法,有没有无参构造方法呢?没有啊.所以,创建 一个参数的构造方法.参数类型是java.lang.reflect.InvocationHandler。 

JAVA如何实现动态代理技术

下面我们来实现:

定义一个上述接口的实例:

package study.javaenhance;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args)   throws Throwable {  // TODO Auto-generated method stub  return null; }}

调用实现创建实例动态类:

//3.创建实例对象  System.out.println("----------begin create instance object----------");  Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);  MyInvocationHandler myInvocationHandler = new MyInvocationHandler();  Collection collection = (Collection) constructor.newInstance(myInvocationHandler);  System.out.println(collection);  collection.clear();  //collection.size(); //报错,异常会发生,产生异常的原因在于其返回值为int类型,但是每一次调用一个方法都会调用到invoke方法,我们此时的invoke返回的为null,所以是没有办法转换为int类型的。

我们采用匿名内部类的方式优化

//3.1 采用匿名内部类方式进行创建  Collection collection2 = (Collection) constructor.newInstance(new InvocationHandler()  {   @Override   public Object invoke(Object proxy, Method method, Object[] args)     throws Throwable {    // TODO Auto-generated method stub    return null;   }     });  System.out.println(collection2);  collection2.clear();  //collection2.size();

继续优化:思考如果我们每次都想上面方式去创建动态的代理类实在有点重复,那么这个是jdk的Proxy类中提供了简单的方法直接去创建动态代理类,方式如下:

//3.3 采用Proxy 中提供的简单方法创建  Collection collection3 = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),    new Class[]{Collection.class},    new InvocationHandler()  {   private ArrayList target = new ArrayList();   @Override   public Object invoke(Object proxy, Method method, Object[] args)     throws Throwable {    return method.invoke(target, args);   }     });  //System.out.println(collection3);  collection3.add("abc");  collection3.add("def");  collection3.add("hij");  System.out.println(collection3.size());

三、动态代理的原理简单分析

上面我们创建了动态代理类,下面我们分析下代理的原理:

 JAVA如何实现动态代理技术

 下面在来看一个问题:

JAVA如何实现动态代理技术

动态代理的工作原理图:

JAVA如何实现动态代理技术

对上面的这个图,我们简单来说说:客户端动态生成代理类,然后调用代理类的方法,代理类内部调用handler.invoke()方法,在invoke中呢,我们又指向的目标类.这样就实现了代理了.我客户端调用代理的什么方法,invoke就只向目标类的同一个方法.而在指定目标类方法的前后呢,我们还可以做其他的操作,比如记录日志.图中用圈圈出来的部分就是代理类自己实现的功能了.这就是代理类的原理.

JAVA如何实现动态代理技术

我们来做最后一步,将上面的动态生成的代理类,编写可生成代理和插入通告的通用方法:

 JAVA如何实现动态代理技术

test代码:

package study.javaenhance;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.Collection;public class ProxyTest{ public static void main(String[] args) throws Exception {  Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);  System.out.println(clazzProxy1.getName());    //上面输出的为一个类,那么一个类肯定有其构造方法和方法,下面我们来列出来    System.out.println("----------begin constructors list----------");  //1.列出构造方法  Constructor[] constructors = clazzProxy1.getConstructors();  for (Constructor constructor : constructors)   {   String name = constructor.getName();   StringBuilder sBuilder = new StringBuilder(name);   sBuilder.append('(');   Class[] clazzParams = constructor.getParameterTypes();   for (Class clazzParam : clazzParams) {    sBuilder.append(clazzParam.getName()).append(',');   }   if(clazzParams!=null && clazzParams.length != 0)    sBuilder.deleteCharAt(sBuilder.length()-1);   sBuilder.append(')');   System.out.println(sBuilder.toString());   }    //2.列出这个类字节码中的所有方法  System.out.println("----------begin methods list----------");  Method[] methods = clazzProxy1.getMethods();  for(Method method : methods){   String name = method.getName();   StringBuilder sBuilder = new StringBuilder(name);   sBuilder.append('(');   Class[] clazzParams = method.getParameterTypes();   for(Class clazzParam : clazzParams){    sBuilder.append(clazzParam.getName()).append(',');   }   if(clazzParams!=null && clazzParams.length != 0)    sBuilder.deleteCharAt(sBuilder.length()-1);   sBuilder.append(')');   System.out.println(sBuilder.toString());     }    //3.创建实例对象  System.out.println("----------begin create instance object----------");  Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);  MyInvocationHandler myInvocationHandler = new MyInvocationHandler();  Collection collection = (Collection) constructor.newInstance(myInvocationHandler);  System.out.println(collection);  collection.clear();  //collection.size(); //报错,异常会发生,产生异常的原因在于其返回值为int类型,但是每一次调用一个方法都会调用到invoke方法,我们此时的invoke返回的为null,所以是没有办法转换为int类型的。    //3.1 采用匿名内部类方式进行创建  Collection collection2 = (Collection) constructor.newInstance(new InvocationHandler()  {   @Override   public Object invoke(Object proxy, Method method, Object[] args)     throws Throwable {    // TODO Auto-generated method stub    return null;   }     });  System.out.println(collection2);  collection2.clear();  //collection2.size();    //3.3 采用Proxy 中提供的简单方法创建  Collection collection3 = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),    new Class[]{Collection.class},    new InvocationHandler()  {   private ArrayList target = new ArrayList();   @Override   public Object invoke(Object proxy, Method method, Object[] args)     throws Throwable {    return method.invoke(target, args);   }     });  //System.out.println(collection3);  collection3.add("abc");  collection3.add("def");  collection3.add("hij");  System.out.println(collection3.size());  System.out.println(collection3.getClass().getName());//这个返回的是    System.out.println("----------begin create instance object 抽化----------");  //3.4抽出动态代理让目标对象和切面对象都是传入进去的    final ArrayList target = new ArrayList();  Collection collection4 = (Collection)getProxy(target,new MyAdvice());  collection4.add("test1");  collection4.add("test2");  System.out.println(collection4.size()); } private static Object getProxy(final Object target,final Advice advice) {  Object object = Proxy.newProxyInstance(target.getClass().getClassLoader(),    target.getClass().getInterfaces(),    new InvocationHandler()  {   @Override   public Object invoke(Object proxy, Method method, Object[] args)     throws Throwable {    advice.beforeMethod(method);    Object retValue = method.invoke(target, args);    advice.afterMethod(method);    return retValue;   }     });  return object; }}

四、实现类似Spring的可配置的AOP框架

首先,我们要完成的要求如下:

JAVA如何实现动态代理技术

我们来模拟spring的工厂模式读取从配置文件传递过来的类。如果这个类是一个普通类则直接返回。如果是一个代理类,则创建代理对象,返回代理类。

具体的理论知识可以看上面的图片

首先创建一个BeanFactory.java类。这是一个Bean工厂,用于读取配置文件中的类

package study.javaenhance.aopframework;import java.io.IOException;import java.io.InputStream;import java.util.Properties;import study.javaenhance.Advice;public class BeanFactory { private Properties properties = new Properties();   public BeanFactory(InputStream inStream) {  try   {   properties.load(inStream);  }  catch (IOException e)   {   e.printStackTrace();  }  finally  {   if(inStream != null)   {    try     {     inStream.close();    }    catch (IOException e)    {     e.printStackTrace();    }   }  } }  public Object getBean(String name) {  String className = properties.getProperty(name);  Object bean = null;  try  {   Class clazz = Class.forName(className);   bean = clazz.newInstance();   if(bean instanceof ProxyFactoryBean)   {    ProxyFactoryBean proxyBean = (ProxyFactoryBean) bean;    Advice advice = (Advice)Class.forName(properties.getProperty(name + ".advice")).newInstance();    Object target = Class.forName(properties.getProperty(name + ".target")).newInstance();    proxyBean.setAdvice(advice);    proxyBean.setTarget(target);    Object proxy = proxyBean.getProxy();    return proxy;   }  }   catch (Exception e)   {   // TODO Auto-generated catch block   e.printStackTrace();  }  return bean; }}

如果这个类中包含ProxyFactoryBean,则调用ProxyFactoryBean中的getProxy方法。动态生成代理类。
ProxyFactoryBean.java

package study.javaenhance.aopframework;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import study.javaenhance.Advice;public class ProxyFactoryBean{ private Object target;  private Advice advice;   public Object getTarget() {  return target; } public void setTarget(Object target) {  this.target = target; } public Advice getAdvice() {  return advice; } public void setAdvice(Advice advice) {  this.advice = advice; } public Object getProxy()  {  Object object = Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),    new InvocationHandler()  {   @Override   public Object invoke(Object proxy, Method method, Object[] args)     throws Throwable {    advice.beforeMethod(method);    Object retValue = method.invoke(target, args);    advice.afterMethod(method);    return retValue;   }     });  return object; }}

接下来创建一个config.Properties文件.config.Properties

xxx=java.util.ArrayList
#xxx=study.javaenhance.aopframework.ProxyFactoryBean
xxx.advice=study.javaenhance.MyAdvice
xxx.target=java.util.ArrayList

最后建立测试类:

package study.javaenhance.aopframework;import java.io.InputStream;import java.util.Collection;public class AopFrameworkTest{ public static void main(String[] args) {  InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");  Object bean = new BeanFactory(ips).getBean("xxx");  System.out.println(bean.getClass().getName());  ((Collection)bean).clear(); }}

以上是“JAVA如何实现动态代理技术”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: JAVA如何实现动态代理技术

本文链接: https://www.lsjlt.com/news/222004.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JAVA如何实现动态代理技术
    这篇文章主要为大家展示了“JAVA如何实现动态代理技术”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JAVA如何实现动态代理技术”这篇文章吧。一、引出动态代理生活中代理应该是很常见的,比如你可以...
    99+
    2023-05-30
    java
  • Java动态代理如何实现
    本篇内容介绍了“Java动态代理如何实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!JDK动态代理:利用反射机制生成一个实现代理接口的匿名...
    99+
    2023-06-30
  • Java如何实现JDK动态代理
    这篇文章主要讲解了“Java如何实现JDK动态代理”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java如何实现JDK动态代理”吧!概念代理:为控制A对象,而创建出新B对象,由B对象代替执行...
    99+
    2023-07-02
  • java动态代理实现代码
    目录1、代理模式2、动态代理3、原理研究4、应用5、总结1、代理模式 代理模式是常用的设计模式之一,也是开发中常见的设计模式。 简单的描述一下,代理模式就是将实现类隔离开,比如你想给...
    99+
    2022-11-12
  • Java实现动态代理的实例代码
    目录前言静态代理 动态代理 CGLib实现动态代理 总结前言 动态代理在Java中有着广泛的应用,比如Spring AOP、Hibernate数据查询、测试框架的后端mock、RPC...
    99+
    2022-11-12
  • 使用Java怎么实现静态代理和动态代理
    本篇文章为大家展示了使用Java怎么实现静态代理和动态代理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。代理模式代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问。主要解决:在直接...
    99+
    2023-06-14
  • 如何进行Java代理设计模式的静态代理和动态代理实现
    今天就跟大家聊聊有关如何进行Java代理设计模式的静态代理和动态代理实现,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。面试问题:Java里的代理设计模式一共有几种实现方式?这个题目很...
    99+
    2023-06-02
  • java proxy动态代理怎么实现
    在Java中,可以通过使用`java.lang.reflect.Proxy`类来实现动态代理。首先,需要定义一个接口,代表被代理类和...
    99+
    2023-09-09
    java
  • Java中怎么实现动态代理
    今天就跟大家聊聊有关Java中怎么实现动态代理,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、概述 代理是一种设计模式,其目的是为其他对象提供一个代理以控制对某个对象的访问,代理类...
    99+
    2023-06-17
  • 浅谈Java动态代理的实现
    目录一、代理设计模式1.1 什么是代理1.2 代理模式入门二、Java代理的三种实现2.1 静态代理2.2 Java自带的动态代理2.3 cglib实现动态代理三...
    99+
    2022-11-12
  • java动态代理的实现方法
    这篇文章主要介绍“java动态代理的实现方法”,在日常操作中,相信很多人在java动态代理的实现方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java动态代理的实现方法”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-20
  • Java动态代理实现_动力节点Java学院整理
    动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程。通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的...
    99+
    2023-05-31
    java 动态代理 ava
  • 代理模式:JAVA静态代理和动态代理的实例和实现详解
    目录前言静态代理实现简述创建human接口创建接口实现类创建针对接口实现增强操作的代理代理实现效果动态代理实现简述要点:向上转型创建YoungMan接口创建两个接口实现类创建动态代理...
    99+
    2022-11-12
  • Java动态代理模式怎么实现
    这篇文章主要介绍“Java动态代理模式怎么实现”,在日常操作中,相信很多人在Java动态代理模式怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java动态代理模式怎么实现”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-17
  • 怎么在java中实现动态代理
    这篇文章给大家介绍怎么在java中实现动态代理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序。1、说明代...
    99+
    2023-06-14
  • Java动态代理与静态代理实例分析
    这篇文章主要介绍了Java动态代理与静态代理实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java动态代理与静态代理实例分析文章都会有所收获,下面我们一起来看看吧。一、静态代理静态代理的使用静态代理,代...
    99+
    2023-07-02
  • java动态代理实现的原理是什么
    Java动态代理是指在运行时动态生成代理类的技术。它的实现原理主要涉及两个关键组件:接口和InvocationHandler。1. ...
    99+
    2023-09-09
    java
  • Java实现JDK动态代理的原理详解
    目录概念案例静态代理JDK动态代理模式原理分析真相大白概念 代理:为控制A对象,而创建出新B对象,由B对象代替执行A对象所有操作,称之为代理。一个代理体系建立涉及到3个参与角色:真实...
    99+
    2022-11-13
  • JDK动态代理,代理接口没有实现类,实现动态代理方式
    目录JDK动态代理,代理接口没有实现类,实现动态代理被代理的接口:代理对象:那么接下来测试一下:jdk动态代理为什么要接口先通过一个简单例子实现功能:编写测试方法:里面的getPro...
    99+
    2022-11-12
  • Java 动态代理的多种实现方式
    目录一、动态代理简介二、动态代理的多种实现 1. 基于JDK的实现 2. 基于cglib的实现 三、为什么要有基于cglib的实现 四、两种方式的适用场景JDK动态代理 优点 缺点 ...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作