Java设计模式学习06——静态代理与动态代理(转)

原地址:http://blog.csdn.net/xu__cg/article/details/52970885

一、代理模式



为某个对象提供一个代理,从而控制这个代理的访问。代理类和委托类具有共同的父类或父接口,这样在任何使用委托类对象的地方都可以使用代理类对象替代。代理类负责请求的预处理、过滤、将请求分配给委托类处理、以及委托类处理完请求的后续处理。

二、代理模式结构



UML类图:

由上图代理模式的结构为:

  • 抽象角色: 真实对象和代理对象的共同接口。
  • 代理角色: 代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
  • 真实角色: 代理角色所代表的真实对象,是我们最终要引用的对象。

根据代理类的生成时间不同可以将代理分为静态代理和动态代理两种。

三、静态代理



由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。 
示例代码: 
1.抽象角色

public interface AbstractSubject {
     void doSomething();
}

2.代理角色

public class ProxySubject implements AbstractSubject{
     private AbstractSubject  real ;
     public ProxySubject(AbstractSubject  real) {
         this.real=real ;
    }
     @Override
     public void doSomething() {

         real.doSomething();
    }

     public void doOtherthing() {

    }
}

3.真实角色

public class RealSubject implements AbstractSubject{
     @Override
     public void doSomething() {
        System.out.println( "真实角色被使用" );
    }
}

4.客户端

public class Client {
     public static void main(String[]  args ) {
        RealSubject real = new  RealSubject();
        ProxySubject proxy = new  ProxySubject( real );
         proxy.doSomething();
    }
}   

5.静态代理的优缺点

优点: 业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。 
缺点:

  • 代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
  • 如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。

四、动态代理



动态代理类的源码是程序在运行期间由JVM根据反射等机制动态生成的,所以不存在代理类的字节码文件。代理角色和真实角色的联系在程序运行时确定。 
1.首先看看和动态代理相关JavaAPI 
① .Java.lang.reflect.Proxy 
这是Java动态代理机制生成的所有代理类的父类,它提供了一组静态的方法来为一组接口动态的生成代理类及其对象。 
Proxy类的静态方法:

//方法 1: 该方法用于获取指定代理对象所关联的调用处理器
static InvocationHandler getInvocationHandler(Object proxy )  

//方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static Class getProxyClass(ClassLoader loader,Class[] interfaces)  

//方法 3:该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl )    

//方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader,  Class[] interfaces, InvocationHandler  h )   

②.java.lang.reflect.InvocationHandler 
这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。每次生成动态代理类对象时都要指定一个对应的调用处理器对象。 
InvocationHandler核心方法

//该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象
//第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行
Object invoke(Object proxy, Method  method,Object[] args )     

③ .java.lang.reflect.ClassLoader 
  这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。每次生成动态代理类对象时都需要指定一个类装载器对象 。

2.动态代理实现步骤

  • 实现InvocationHandler接口创建自己的调用处理器 。
  • 给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类 。
  • 执行真实角色具体任务。

示例代码

1.抽象角色和真实角色代码与上述相同 。 
2. 创建自己的调用处理器:

public class SubjectHandler implements InvocationHandler{
    AbstractSubject real;
    public SubjectHandler(AbstractSubject real){
        this.real=real;
    }

    @Override
    public Object invoke(Object obj, Method method, Object[] args)throws Throwable {
        System.out.println("代理类预处理任务");
        //利用反射机制将请求分派给委托类处理。Method的invoke返回Object对象作为方法执行结果。
  //因为示例程序没有返回值,所以这里忽略了返回值处理
        method.invoke(real, args);
        System.out.println("代理类后续处理任务");
        return null;
    }

}

3.客户端 :

public class Client {

    public static void main(String[] args) {
        RealSubject real=new RealSubject();
        SubjectHandler handler=new SubjectHandler(real);
        //生成代理类对象
        AbstractSubject proxy=(AbstractSubject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{AbstractSubject.class},handler);
        proxy.doSomething();

    }

}

4.动态代理的优缺点

优点: 
  动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。

不足: 
  诚然,Proxy 已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。

本文动态代理部分内容大量引自:http://layznet.iteye.com/blog/1182924

时间: 2024-10-13 09:07:27

Java设计模式学习06——静态代理与动态代理(转)的相关文章

JAVA学习篇--静态代理VS动态代理

本篇博客的由来,之前我们学习大话设计,就了解了代理模式,但为什么还要说呢? 原因: 1,通过DRP这个项目,了解到了动态代理,认识到我们之前一直使用的都是静态代理,那么动态代理又有什么好处呢?它们二者的区别是什么呢? 2,通过学习动态代理了解到动态代理是一种符合AOP设计思想的技术,那么什么又是AOP? 下面是我对它们的理解! 代理Proxy: Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对

深入浅出java静态代理和动态代理

首先介绍一下,什么是代理: 代理模式,是常用的设计模式.特征是,代理类与委托类有相同的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类.以及事后处理消息. 代理类和委托类,存在着关联关系.代理类的对象本身并不真正实现服务,知识通过调用委托类的对象的相关方法. 代理类可以分为两种:静态代理和动态代理. 静态代理: 代理类是由程序员创建,或由工具生成的代码 编译成的.在程序运行前,代理类的 *.class文件已经存在了.直接就可以运行 . 动态代理: 动态代理的代理类.没有直接由

【java项目实战】代理模式(Proxy Pattern),静态代理 VS 动态代理

这篇博文,我们主要以类图和代码的形式来对照学习一下静态代理和动态代理.重点解析各自的优缺点. 定义 代理模式(Proxy Pattern)是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用. 代理模式不会改变原来的接口和行为,仅仅是转由代理干某件事,代理能够控制原来的目标,比如:代理商,代理商仅仅会买东西,但并不会改变行为.不会制造东西. 让我们通过以下的代码好好理解一下这句话. 分类 静态代理和动态代理 静态代理 静态代理类图 代码演示样例 接口 pac

Java:静态代理and动态代理

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

java 代理模式(静态代理、动态代理、Cglib代理) 转载

Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法 代理模式最大的特点就是代理类和实际业务类实现同一个接口(或继承同一父类),代理对象持有一个实际对象的引用,外部调用时操作的是代理对象,而在代理对象的内部实现中又会去调

java静态代理和动态代理(一)

代理Proxy: Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题. 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从

设计模式之--静态代理及动态代理模式

原文链接:http://www.studyshare.cn/blog/details/1181/0 一.概念 代理模式:为其他对象提供一种代理类用以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用 另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用,代理模式属于23中设计模式中的结构型设计模式. 代理模式可分为静态代理和动态代理. 代理结构如下图: 例如:客户(客户类)—>代购(代理类)—>海外下单(海外订单类),普通客户无法直接去海外下单,则向代购公司 下单,代

JAVA设计模式学习--代理模式

学习还是先从定义开始,反复的琢磨对模式的定义会让自己更深刻的记住. 代理模式定义:在某些场景下,系统中的目标对象不能被直接引用或者不适合直接引用,这时需要一个代理,起中介的作用以达到控制和增强目标对象. 代理模式分类:静态代理.动态代理. 代理模式结构: 1.抽象主题 2.真实主题 3.代理对象 上代码 静态代理 //抽象主题 public interface Target { public void display(); } //真实主题 public class RealTarget imp

【Java】代处理?代理模式 - 静态代理,动态代理

>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算,见[Java]Float计算不准确) package com.nicchagil.study.java.demo.No09代理.No01不用代理; import java.math.BigDecimal; public class FloatCalculator { public float add(fl