iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java动态代理实现_动力节点Java学院整理
  • 578
分享到

Java动态代理实现_动力节点Java学院整理

java动态代理ava 2023-05-31 08:05:34 578人浏览 薄情痞子
摘要

动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于aop的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程。通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的

动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于aop的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程。

通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的方法都被固定,这种代理被称之为静态代理(Static Proxy)。那么有没有一种机制能够让系统在运行时动态创建代理类?答案就是本文将要介绍的动态代理(Dynamic Proxy)。动态代理是一种较为高级的代理模式,它在事务管理、AOP(Aspect-OrientedProgramming,面向方面编程)等领域都发挥了重要的作用。

在传统的代理模式中,客户端通过Proxy类调用RealSubject类的request()方法,同时还可以在代理类中封装其他方法(如preRequest()和postRequest()等)。如果按照这种方法使用代理模式,那么代理类和真实主题类都应该是事先已经存在的,代理类的接口和所代理方法都已明确指定,如果需要为不同的真实主题类提供代理类或者代理一个真实主题类中的不同方法,都需要增加新的代理类,这将导致系统中的类个数急剧增加,因此需要想办法减少系统中类的个数。动态代理可以让系统能够根据实际需要来动态创建代理类,让同一个代理类能够代理多个不同的真实主题类而且可以代理不同的方法。

jdk 1.3开始,Java语言提供了对动态代理的支持,Java语言实现动态代理时需要用到位于java.lang.reflect包中的一些类,现简要说明如下:

 (1) Proxy类

 Proxy类提供了用于创建动态代理类和实例对象的方法,它是所创建的动态代理类的父类,它最常用的方法如下:

  • public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces):该方法用于返回一个Class类型的代理类,在参数中需要提供类加载器并需要指定代理的接口数组(与真实主题类的接口列表一致)。
  • public static Object newProxyInstance(ClassLoader loader, Class<?>[]interfaces, InvocationHandler h):该方法用于返回一个动态创建的代理类的实例,方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示代理类所实现的接口列表(与真实主题类的接口列表一致),第三个参数h表示所指派的调用处理程序类。

 (2) InvocationHandler接口

InvocationHandler接口是代理处理程序类的实现接口,该接口作为代理实例的调用处理者的公共父类,每一个代理类的实例都可以提供一个相关的具体调用处理者(InvocationHandler接口的子类)。在该接口中声明了如下方法:

public Object invoke(Objectproxy, Method method, Object[] args):该方法用于处理对代理类实例的方法调用并返回相应的结果,当一个代理实例中的业务方法被调用时将自动调用该方法。invoke()方法包含三个参数,其中第一个参数proxy表示代理类的实例,第二个参数method表示需要代理的方法,第三个参数args表示代理方法的参数数组。

动态代理类需要在运行时指定所代理真实主题类的接口,客户端在调用动态代理对象的方法时,调用请求会将请求自动转发给InvocationHandler对象的invoke()方法,由invoke()方法来实现对请求的统一处理。

下面通过一个简单实例来学习如何使用动态代理模式:

Sunny软件公司欲为公司OA系统数据访问层DAO增加方法调用日志,记录每一个方法被调用的时间和调用结果,现使用动态代理进行设计和实现。

本实例完整代码如下所示:

import java.lang.reflect.Proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Calendar; import java.util.GreGorianCalendar;  //抽象UserDAO:抽象主题角色 interface AbstractUserDAO {   public Boolean findUserById(String userId); }  //抽象DocumentDAO:抽象主题角色 interface AbstractDocumentDAO {   public Boolean deleteDocumentById(String documentId); }  //具体UserDAO类:真实主题角色 class UserDAO implements AbstractUserDAO {   public Boolean findUserById(String userId) {     if (userId.equalsIgnoreCase("张无忌")) {       System.out.println("查询ID为" + userId + "的用户信息成功!");       return true;     }     else {       System.out.println("查询ID为" + userId + "的用户信息失败!");       return false;     }   } }  //具体DocumentDAO类:真实主题角色 class DocumentDAO implements AbstractDocumentDAO {   public Boolean deleteDocumentById(String documentId) {     if (documentId.equalsIgnoreCase("D001")) {       System.out.println("删除ID为" + documentId + "的文档信息成功!");       return true;     }     else {       System.out.println("删除ID为" + documentId + "的文档信息失败!");       return false;     }   } }  //自定义请求处理程序类 class DAOLogHandler implements InvocationHandler {   private Calendar calendar;   private Object object;      public DAOLogHandler() {     }      //自定义有参构造函数,用于注入一个需要提供代理的真实主题对象   public DAOLogHandler(Object object) {     this.object = object;   }      //实现invoke()方法,调用在真实主题类中定义的方法   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {     beforeInvoke();     Object result = method.invoke(object, args); //转发调用     afterInvoke();     return null;   }    //记录方法调用时间   public void beforeInvoke(){     calendar = new GregorianCalendar();     int hour = calendar.get(Calendar.HOUR_OF_DAY);     int minute = calendar.get(Calendar.MINUTE);     int second = calendar.get(Calendar.SECOND);     String time = hour + ":" + minute + ":" + second;     System.out.println("调用时间:" + time);   }    public void afterInvoke(){     System.out.println("方法调用结束!" );   } } 

--结束END--

本文标题: Java动态代理实现_动力节点Java学院整理

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

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

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

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

下载Word文档
猜你喜欢
  • Java动态代理实现_动力节点Java学院整理
    动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程。通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的...
    99+
    2023-05-31
    java 动态代理 ava
  • Java多态(动力节点Java学院整理)
    什么是多态 面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。 多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象...
    99+
    2023-05-31
    java 多态 ava
  • Java死锁_动力节点Java学院整理
    死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。在这里我已写好一个简单的程序,它将会引起死锁方案然后我们就会明白如何分析它。Java死锁范例ThreadDeadlock.javapack...
    99+
    2023-05-31
    java 死锁 ava
  • Java Set简介_动力节点Java学院整理
    1. 概述           Java 中的Set和正好和数学上直观的集(set)的概念是相同的。Set最大的特性就是不允许在其中存放的元素是重复的...
    99+
    2023-05-31
    java set ava
  • Java Map简介_动力节点Java学院整理
    Map简介将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。此接口取代 Dictionary 类,后者完全是一个抽象类,而不是一个接口。 Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关...
    99+
    2023-05-31
    java map ava
  • Java 线程池_动力节点Java学院整理
    线程池系统启动一个新线程的成本是比较高的,因为它涉及到与操作系统的交互。在这种情况下,使用线程池可以很好的提供性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池。与数据库连接池类似的是,线程池在系统启动时即创建大量空...
    99+
    2023-05-31
    java 线程池 ava
  • Java FileDescriptor总结_动力节点Java学院整理
    FileDescriptor 介绍FileDescriptor 是“文件描述符”。FileDescriptor 可以被用来表示开放文件、开放套接字等。以FileDescriptor表示文件来说:当FileDescriptor表示某文件时,我...
    99+
    2023-05-31
    java filedescriptor ava
  • Java链接redis_动力节点Java学院整理
    要在Java程序中使用使用操作Redis,需要确保有Redis的Java驱动程序和Java设置在机器上。现在,让我们来看看如何设置Redis的Java驱动程序。 需要下载jedis.jar。请一定要下载它的最新版本。 需要包括jedis...
    99+
    2023-05-31
    java redis 链接
  • Java内部类_动力节点Java学院整理
    内部类是指在一个外部类的内部再定义一个类。类名不需要和文件夹相同。内部类可以是静态static的,也可用public,default,protected和private修饰。(而外部顶级类即类名和文件名相同的只能使用public和defau...
    99+
    2023-05-31
    java 内部类 ava
  • redis简介_动力节点Java学院整理
    Redis是一个开源的,先进的 key-value 存储可用于构建高性能,可扩展的 Web 应用程序的解决方案。Redis官方网网站是:http://www.redis.io/,如下: Redis 有三个...
    99+
    2022-06-04
    节点 动力 简介
  • redis事务_动力节点Java学院整理
    我们都知道redis追求的是简单,快速,高效,在这种情况下也就拒绝了支持window平台,学sqlserver的时候,我们知道事务还算是个比较复杂的东西,所以这要是照搬到redis中去,理所当然redis就...
    99+
    2022-06-04
    节点 事务 动力
  • JDBC简介_动力节点Java学院整理
    前言:什么是JDBC维基百科的简介:  Java 数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。J...
    99+
    2023-05-31
    jdbc 简介 ava
  • Ehcache简介_动力节点Java学院整理
    使用Spring的AOP进行整合,可以灵活的对方法的返回结果对象进行缓存。CachingFilter功能可以对HTTP响应的内容进行缓存。1、主要特性     1. 快速.  &n...
    99+
    2023-05-31
    ehcache ava hcache
  • Java线程之join_动力节点Java学院整理
    join()介绍join() 定义在Thread.java中。join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。这句话可能有点晦涩,我们还是通过例子去理解: // 主线程public class Father ...
    99+
    2023-05-31
    java 线程 join
  • Java线程让步_动力节点Java学院整理
    yield()介绍yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可...
    99+
    2023-05-31
    java 线程让步 ava
  • Java Scaner类详解_动力节点Java学院整理
    Java.util.Scanner是Java5.0的新特征,主要功能是简化文本扫描。这个类最实用的地方表现在获取控制台输入,其他的功能都很鸡肋,尽管Java API文档中列举了大量的API方法,但是都不怎么地。 一、扫描控制台输入...
    99+
    2023-05-31
    java scaner
  • Java Runtime类详解_动力节点Java学院整理
    一、概述      Runtime类封装了运行时的环境。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。一般不能实例化一个Runtime对象,应...
    99+
    2023-05-31
    java runtime
  • Java中StringBuffer和StringBuilder_动力节点Java学院整理
    下面先给大家介绍下String、StringBuffer、StringBuilder区别,具体详情如下所示:StringBuffer、StringBuilder和String一样,也用来代表字符串。String类是不可变类,任何对Strin...
    99+
    2023-05-31
    java stringbuffer stringbuilder
  • Java concurrency之集合_动力节点Java学院整理
    Java集合包Java集合主体内容包括Collection集合和Map类;而Collection集合又可以划分为List(队列)和Set(集合)。1. List的实现类主要有: LinkedList, ArrayList, Vector, ...
    99+
    2023-05-31
    java concurrency ava
  • Java中Random简介_动力节点Java学院整理
    Java中存在着两种Random函数:一、java.lang.Math.Random;  调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范围是[0.0,1.0)的左闭右开区间,返...
    99+
    2023-05-31
    java random ava
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作