`
20921556
  • 浏览: 93615 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

java 动态代理 复习

阅读更多
代理模式代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。(参见文献1)
以下以《Java与模式》中的示例为例:
抽象角色:
abstract public class Subject 
{ 
    abstract public void request(); 
} 
真实角色:实现了Subject的request()方法。
public class RealSubject extends Subject 
{ 
       public RealSubject() 
       { 
       } 
       
       public void request() 
       { 
              System.out.println("From real subject."); 
       } 
} 代理角色: 
public class ProxySubject extends Subject 
{ 
    private RealSubject realSubject;  //以真实角色作为代理角色的属性 
       
       public ProxySubject() 
       { 
       } 

       public void request()  //该方法封装了真实对象的request方法 
       { 
        preRequest();   
              if( realSubject == null ) 
        { 
                     realSubject = new RealSubject(); 
              } 
        realSubject.request();  //此处执行真实对象的request方法 
        postRequest(); 
       } 

    private void preRequest() 
    { 
        //something you want to do before requesting 
    } 

    private void postRequest() 
    { 
        //something you want to do after requesting 
    } 
} 

客户端调用:
Subject sub=new ProxySubject();
Sub.request();
       由以上代码可以看出,客户实际需要调用的是RealSubject类的request()方法,现在用ProxySubject来代理RealSubject类,同样达到目的,同时还封装了其他方法(preRequest(),postRequest()),可以处理一些其他问题。
       另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。

2.动态代理类
       Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, J2EEjava语言JDK1.4APIjavalangObject.html">Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。

(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:
Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object [url=file:///D:技术文档J2EEjava语言JDK1.4APIjavalangreflectProxy.html#newProxyInstance(java.lang.ClassLoader, java.lang.Class[], java.lang.reflect.InvocationHandler)]newProxyInstance[/url](ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。


       所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。(参见文献3)
    在使用动态代理类时,我们必须实现InvocationHandler接口,以第一节中的示例为例:
抽象角色(之前是抽象类,此处应改为接口):
public interface Subject
{
    abstract public void request();
}
具体角色RealSubject:同上;

代理角色: 
import java.lang.reflect.Method; 
import java.lang.reflect.InvocationHandler; 

public class DynamicSubject implements InvocationHandler { 
  private Object sub; 

  public DynamicSubject() { 
  } 

  public DynamicSubject(Object obj) { 
    sub = obj; 
  } 


  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
    System.out.println("before calling " + method); 

    method.invoke(sub,args); 

    System.out.println("after calling " + method); 
    return null; 
  } 

} 

       该代理类的内部属性为Object类,实际使用时通过该类的构造函数DynamicSubject(Object obj)对其赋值;此外,在该类还实现了invoke方法,该方法中的
method.invoke(sub,args);
其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,args为执行被代理对象相应操作所需的参数。通过动态代理类,我们可以在调用之前或之后执行一些相关操作。
客户端:
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Proxy; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.Method; 

public class Client 
{ 

    static public void main(String[] args) throws Throwable 
       { 
      RealSubject rs = new RealSubject();  //在这里指定被代理类 
      InvocationHandler ds = new DynamicSubject(rs);  //初始化代理类 
         Class cls = rs.getClass(); 
      //以下是分解步骤 
      /* 
      Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()) ; 
      Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class}); 
      Subject subject =(Subject) ct.newInstance(new Object[]{ds}); 
     */ 
     //以下是一次性生成 
      Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), 
                                 cls.getInterfaces(),ds ); 


      subject.request(); 
} 
       通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系(参见文献2)。

更多请进入code110技术导航网
分享到:
评论

相关推荐

    java-jdk动态代理的实现demo

    实现了一份jdk动态代理的demo,做了详细注释,供以后复习使用,另外,这里为什么需要大于100个字节才能传资源?我就不想那么多不行吗???

    661.659.JAVA基础教程_动态代理与Java8新特性-复习:ClassLoader(661).rar

    661.659.JAVA基础教程_动态代理与Java8新特性-复习:ClassLoader(661).rar

    复习反射利用反射机制和AOP代理模式

    reflection是一系列的API,用于表示或者处理当前JVM中的类,接口和对象. java.lang.reflect/java.lang.Class 在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

    15.1.6 动态代理 512 15.2 了解类加载器 515 15.2.1 类加载器层级架构 515 15.2.2 建立classloader实例 518 15.3 重点复习 520 15.4 课后练习 521 chapter16 自定义泛型、枚举与标注 523 16.1 自定义...

    java进阶13天资料.zip

    Java进阶13天资料 day01-复习回顾、静态、继承、引用类型使用 day02-抽象类、接口、代码块,final、...day12-JUnit单元测试、反射、注解、动态代理 day13-XML和Dom4j,装饰模式,工厂模式,commons-io工具包,Base64

    javasnmp源码-java_review:复习资料

    JDK动态代理和cgLib动态代理 ​ ​ ​ sprin创建bean过程 ​ ​ SpringMVC常用注解 ​ springMVC处理请求流程/工作流程 ​ ​ SpringMVC @RequestParam,@PathParam,@PathVariable等注解区别 ​ ...

    java设计模式选择题复习题.doc

    行为型特点:怎样合理的设计对象之间的交互通信,以及怎样合理的为对象分配职 结构型特点:主要用于处理类或对象的组合 Java jdk中使用了哪些设计模式 1.单例2.静态工厂3.工厂方法4.抽象工厂5.构造者6.原型7.适配器...

    leetcode18java-StudyDayUp:基于java数据结构、算法、leetcode题目讲解,23种设计模式全面复习

    全面复习 一、java 1、java基础知识 2、java容器 3、java并发 4、java虚拟机 5、java IO 二、设计模式 1. 单例模式 2. 原型模式 3. 工厂方法模式 4. 抽象工厂模式 5. 建造者模式 Bulider模式 6. 结构型模式 7. 代理...

    Java基础知识加强PPT

    本文档适合对Java编程语言有一定了解的朋友复习之用,此PPT涵盖了枚举、反射、JavaBean、注解、泛型、代理等多方面的基础知识,讲解并不详细,但短小精悍,对思维发散很有好处,实用性强

    leetcode分类-Java-grammar1:java学习资料,使用技巧,各方面应用,基于jdk1.8.151版本之前的总结,各个版本更改

    经过在公司一段时间,梳理了github上很多没用的例子,决定从今天开始,每天github打卡,复习一次java也给刚入门的问我问题的人们朋友们一点自己亲手打的例子 每日更新文件前缀在 team.wt.javalearn.java.src.main.day* ...

    design-pattern-java.pdf

    设计模式趣味学习(复习) 设计模式趣味学习(复习) 设计模式与足球(一) 设计模式与足球(二) 设计模式与足球(三) 设计模式与足球(四) 设计模式综合应用实例 设计模式综合应用实例 多人联机射击游戏 多人...

    J2EE程序设计复习题.doc

    J2EE程序设计复习题 1. 选择题 1. EJB是: [B] A. 服务器端产品 B. 服务器端组件开发架构 C. 特殊类型的JavaBean D. 用于实现商业逻辑 2. EJB架构主要使用的设计模式是: [AC] A. Proxy 代理 B. Strategy C. ...

    30天搞定Java–day29(完)

    文章目录每日一考和复习反射反射的应用:动态代理Java 8 的其他新特性Lambda表达式函数式(Functional)接口方法引用与构造器引用方法引用构造器调用强大的Stream APIStream的实例化中间操作终止操作Optional类 ...

    新MyBatis教程高手带你练手,玩框架轻松(3.15G)

    MyBatis-001-三层架构.avi MyBatis-002-框架概念.avi MyBatis-003-jdbc缺陷.avi MyBatis-004-MyBatis能做什么.avi MyBatis-005-使用步骤.avi MyBatis-006-创建mapper文件.avi ...MyBatis-019-动态代理getMapper.

    拦截器和控制器的区别

    1、拦截器基于动态代理 , 过滤器基于函数回调 2、拦截器不依赖于servlet容器,通过动态代理实现,过滤器依赖于servlet容器 3、拦截器在方法前后,异常前后等调用,而过滤器只能在请求前和请求后各调一次。 4、拦截...

    reids的入门学习1

    最近在深入学习redis,以前只是用过,没有整理过,现在整理一下,方便以后面试时复习。 1.redis是什么? 打开redis的官网(https://redis.io/topics/introduction),可以看到 redis是一款--【开源的(BSD许可)...

    Head.First设计模式_PDF.part1

    每章最后有一页要点整理,这也是精华所在,我都是利用这一页做复习。  《Head First设计模式》共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式。前言先介绍这本书的用法;第1章到第...

    中间件期末考超强文档合集.rar

    中间件期末考复习资料包含三个文档 一、课堂考点、重点题目、考试方向思考题全解 1.什么是消息型中间件 queue 和 topic 是什么意思 答: (1) 定义:消息中间件是分布式系统中完成消息发送和接收的基本软件。 消息...

    leetcode答案-Data-Structure-and-Algorithms:数据结构与算法

    复习资料 一篇文章有的段落没看懂没关系,记下来继续往下看,从其他文章中找答案。文章都是人写的、没经过校对,出现不理解的段落很正常。多读多搜索其他的文章,从其他文章中找问题的解释。 网络基础 TCP/IP协议 ...

    Eclipse开发分布式商城系统+完整视频代码及文档

    │ │ 深入理解Java内存模型.pdf │ │ │ └─课后资料 │ ├─笔记 │ │ 淘淘商城_day20_课堂笔记.docx │ │ │ └─视频 │ 07-使用Jedis连接集群操作.avi │ 00-今日大纲.avi │ 01-RDB持久化方式.avi │ 02...

Global site tag (gtag.js) - Google Analytics