美文网首页
java 代理、静态代理、动态代理

java 代理、静态代理、动态代理

作者: 后尘L | 来源:发表于2019-04-25 17:04 被阅读0次

代理

在某些情况下,客户不想或者不能直接引用另一个对象,这时候代理对象可以在客户端和目标对象之间起到中介的作用。

代理对象提供一种代理以控制对委托对象的访问控制,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。

通常情况下代理类和委托类实现相同的接口或继承相同的父类,代理类中通过聚合方式持有委托类的对象,代理类对象本身并不真正实现服务,而是通过调用委托类对象的相关方法来提供相关服务,并做一些额外操作。

代理的优点:
一、可以隐藏委托类的实现,实现客户与委托类之间的解耦;
二、在不修改委托类代码的情况下能够做一些额外的处理;

按照代理类的创建时间,代理分为静态代理和动态代理。

静态代理

代理类在代码编译之前已经存在叫做静态代理,一般由程序员创建。

静态代理类通常只代理一个委托类。

/**
 * 静态代理类和委托类需要共同实现的接口
 * */
public interface Subject {

    void sell();

    void print(String msg);

}
/**
 * 委托类,实现了接口
 * */
public class RealSubject implements Subject {

    @Override
    public void sell() {
        System.out.println("in sell method");
    }

    @Override
    public void print(String msg) {
        System.out.println("in print method, msg " + msg);
    }

}
/**
 * 静态代理类
 * 也实现了接口,但接口方法和实现是调用了委托类的实现
 * 静态代理类在方法中对委托类的实现进行了增强,甚至过滤
 * */
public class ProxySubject implements Subject {

    private Subject subject;  // 代理类通过聚合持有委托类实现对象的引用

    public ProxySubject(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void sell() {
        System.out.println("before");
        subject.sell();    // 代理类中调用委托类的实现
        System.out.println("after");
    }

    @Override
    public void print(String msg) {
        System.out.println("before");
        subject.print(msg);    // 代理类中调用委托类的实现
        System.out.println("after");
    }

}
public class Client {

    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();  // 事先已存在的委托类对象

        ProxySubject proxySubject = new ProxySubject(realSubject);  // 创建代理类,传入已存在的委托类对象
        proxySubject.sell();  // 调用代理类方法,代理类中调用委托类对象相关方法实现服务
        proxySubject.print("this is message");
    }

}

动态代理

代理类在程序运行时创建的代理方式叫做动态代理。

首先通过newProxyInstance方法创建代理类并获取代理类实例,而后我们便可以通过这个代理类实例调用代理类的方法,对代理类的方法的调用实际上都会调用中介类(调用处理器)的invoke方法,在invoke方法中我们调用委托类的相应方法,并且可以添加自己的处理逻辑。

动态代理的接口和委托类与静态代理相同。

/**
 * 中介类
 * */
public class DynamicProxy implements InvocationHandler {

    // 中介类通过聚合方式持有委托类对象,subject为委托类对象
    // 外部对代理类对象的调用转化为对invoke的调用,invoke内再调委托类对象
    // 中介类与委托类构成了静态代理关系,在这里,中介类就是代理类,委托类就是委托类
    private Object subject;

    public DynamicProxy(Object obj) {
        this.subject = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = method.invoke(subject, args);
        System.out.println("after");
        return result;    // 可以返回 null
    }

}
public class Main {

    public static void main(String[] args) {
        // 创建被委托类对象
        RealSubject vendor = new RealSubject();
        // 创建中介类实例
        DynamicProxy inter = new DynamicProxy(vendor);
        // 加上这句将会产生一个$Proxy0.class文件,这个文件即为动态生成的代理类文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");

        // 获取代理类实例sell
        // 动态生成代理类,代理类的方法由接口指定,代理类方法的调用由handler处理,handler中方法的处理由委托类处理
        Subject proxySubject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class[] {Subject.class}, inter);

        // 通过代理类对象调用代理类方法,实际上会转到invoke方法调用
        proxySubject.sell();
        proxySubject.print("this is message");
    }

}

首先,通过Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class[] {Subject.class}, handler);在程序运行时生成动态代理类。参数1是生成动态代理类的类加载器;参数2是生成的代理类要实现的接口;参数3是调用代理类方法后实际处理方法调用的handler。

当调用代理类对象的方法时,这个“调用”会转送到handler的invoke(Object proxy, Method method, Object[] args)方法中,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,这样我们可以在invoke方法中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)。

中介类通过聚合方式持有一个委托类对象引用,在invoke方法中调用了委托类对象的相应方法,把外部对invoke的调用最终都转为对委托类对象的调用。这就像上面的静态代理的实现方式,实际上,中介类与委托类构成了静态代理关系,在这个关系中,中介类是代理类,委托类就是委托类;代理类与中介类也构成一个静态代理关系,在这个关系中,中介类是委托类,代理类是代理类。也就是说,动态代理关系由两组静态代理关系组成,这就是动态代理的原理。

动态代理与静态代理区别

一、动态代理类代理接口下的所有类,而静态代理通常只代理一个类;
二、动态代理只能代理接口,而静态代理还可以代理普通共同父类;
三、动态代理事先不知道要代理的是什么,只有在运行的时候才能确定。而静态代理在代码编写时就知道;

动态代理的优势

相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。

相关文章

  • 浅谈Java和SAP ABAP的静态代理和动态代理,以及ABAP

    文章目录 Java的静态代理 静态代理的优缺点 ABAP的静态代理 Spring AOP的动态代理 JDK动态代理...

  • java反射和动态代理

    java动态代理Proxy.newProxyInstance 详解java代理机制(静态代理、动态代理)以及使用场景

  • Java动态代理从入门到原理再到实战

    目录 前言 什么是动态代理,和静态代理有什么区别 Java动态代理的简单使用 Java动态代理的原理解读 动态代理...

  • 动态代理的两种方式

    静态代理就不说了,基本用到的都是动态代理。 Java中动态代理有JDK动态代理和CGLIB动态代理。 JDK代理的...

  • 编程常用的设计模式

    动态代理和静态代理 静态代理 动态代理 静态代理与动态代理的区别 JDK中的动态代理和CGLIB 实现动态代理的方...

  • JAVA动态代理的实现方式

    1. 静态代理VS动态代理 代理类可以增强被代理对象的方法。可分为静态代理和动态代理。 1.1 静态代理 静态代理...

  • 带你初识Java的代理模式

    Spring AOP是基于动态代理设计模式实现的,相对的就有静态代理 动态代理和静态代理 静态代理 对于静态代理,...

  • 代理简记

    Java静态代理 委托类和代理类,实现共同接口 共同接口: 委托类: 代理类: 测试结果: Java动态代理 通过...

  • Java代理

    前言 Java代理大致可以分为静态代理(static proxy),动态代理(dynamic proxy)。所谓代...

  • java的动态代理详解(javassist,cglib)

    俗话说:Coder不知动态代理,走在路上没人理!!!所以本文尝试说明白java代理模式,代理中的静态代理和动态代理...

网友评论

      本文标题:java 代理、静态代理、动态代理

      本文链接:https://www.haomeiwen.com/subject/jbwzgqtx.html