Java的动态代理和静态代理详解

目录
  • 0、代理模式
  • 1、静态代理
  • 2、加深理解
  • 3、动态代理
    • 动态代理的例子
  • 总结

0、代理模式

为什么要学习代理模式?这是SpringAOP的底层【SpringAOP和SpringMVC】

代理模式的分类:

  • 静态代理
  • 动态代理

1、静态代理

静态代理中,我们对目标对象的每个方法的增强都是手动完成的(后面会具体演示代码_),非常不灵活(比如接口一旦新增加方法,目标对象和代理对象都要进行修改)且麻烦(_需要对每个目标类都单独写一个代理类)。 实际应用场景非常非常少,日常开发几乎看不到使用静态代理的场景。

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人!

代码步骤:

1、接口

public interface Rent {
    public void rent();
}

2、真实角色

//房东
public class Host implements Rent {
    public void rent() {
        System.out.println("房东要租房子");
    }
}

3、代理角色

public class Proxy implements Rent{
    private Host host;
    public Proxy() {
    }
    public Proxy(Host host) {
        this.host = host;
    }
    public void rent(){
        seeHouse();
        host.rent();
        fare();
    }
    //看房
    public void seeHouse(){
        System.out.println("中介带你看房");
    }
    //收中介费
    public void fare(){
        System.out.println("中介收费");
    }
}

4、客服端访问代理角色

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        //代理,代理角色一般会有附属操作!
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}

代理模式的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
  • 公共也就交给代理角色!实现业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!

缺点:

一个真实角色会产生一个代理角色;从JVM角度来看,静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的class文件。

2、 加深理解

AOP,的底层代理模式

3、动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口——JDK动态代理
    • 基于类:cglib动态代理
    • java字节码实现:javasist

需要了解两个类:Proxy: 代理类,InvocationHandler : 调用处理程序

从 JVM 角度来说,动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。

//Proxy是生成动态代理类,提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
//InvocationHandler-- invoke 调用处理程序并返回接口, 是由代理实例的调用处理程序实现的接口 。

动态代理的好处:

  • 可以使真实角色的操作更加纯粹!不用去关系一些公共的业务
  • 公共也就交给代理角色!实现
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h){
}

1.loader :类加载器,用于加载代理对象。

2.interfaces : 被代理类实现的一些接口;

3.h : 实现了 InvocationHandler 接口的对象;

要实现动态代理的话,还必须需要实现InvocationHandler 来自定义处理逻辑。 当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现InvocationHandler 接口类的 invoke 方法来调用。

public interface InvocationHandler {
    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

1.proxy :动态生成的代理类

2.method : 与代理类对象调用的方法相对应

3.args : 当前 method 方法的参数

动态代理的例子

1、定义接口

public interface Rent {
    public void rent();
}

2、实现租房的接口

public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东要租房");
    }
}

3、定义一个JDK动态代理类

public class DebugInvocationHandler implements InvocationHandler {
    /**
     * 代理类中的真实对象
     */
    private final Object target;
    public DebugInvocationHandler(Object target){
        this.target = target;
    }
    /**
     * 当你使用代理对象调用方法的时候实际会调用到这个方法
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用方法前
        System.out.println("before method" + method.getName());
        Object res = method.invoke(target, args);
        //调用方法后
        System.out.println("after method" + method.getName());
        return res;
    }
}

invoke() 方法: 当我们的动态代理对象调用原生方法的时候,最终实际上调用到的是 invoke() 方法,然后 invoke() 方法代替我们去调用了被代理对象的原生方法。

4、获取代理对象的工厂类

public class JdkProxyFactory {
    public static Object getProxy(Object target){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new DebugInvocationHandler(target)
        );
    }
}

getProxy() :主要通过Proxy.newProxyInstance()方法获取某个类的代理对象

5、实际使用

public static void main(String[] args) {
        //Rent rent = new Host();
        //Rent rentProxy= (Rent) Proxy.newProxyInstance(rent.getClass().getClassLoader(), rent.getClass().getInterfaces(),new DebugInvocationHandler(rent));
        Rent rentProxy = (Rent)JdkProxyFactory.getProxy(new Host());
        rentProxy.rent();
    }

运行上述代理的输出

before methodrent
房东要租房
after methodrent

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java 静态代理与动态代理解析

    目录 一.代码实践 静态代理 动态代理 二.常见的动态代理场景 Retrofit中的动态代理 使用动态代理实现onClick注入 三.源码探索Jdk中的动态代理 生成代理类 四.总结 静态代理: 由我们开发者自己手动创建或者在程序运行前就已经存在的代理类,静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类. 动态代理: 在程序运行时,运用java反射机制动态创建而成,静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道,通常动态代理实现方式是通过实现 j

  • java 静态代理 动态代理深入学习

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

  • 深入解析java中的静态代理与动态代理

    java编码中经常用到代理,代理分为静态代理和动态代理.其中动态代理可以实现spring中的aop. 一.静态代理:程序运行之前,程序员就要编写proxy,然后进行编译,即在程序运行之前,代理类的字节码文件就已经生成了 被代理类的公共父类 复制代码 代码如下: package staticproxy;public abstract class BaseClass {    public abstract void add();} 被代理类 复制代码 代码如下: package staticpro

  • Java静态代理与动态代理案例详解

    代理模式 代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问. 主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上.在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层. 代理模式的元素是:共同接口.代理对象.目标对象. 代理模式的行为:由代理对象执行目标对象的方法.由代理对象扩展目标对象的方法. 代理模式的

  • Java动态代理静态代理实例分析

    代理模式:为其他对象提供一种代理以控制某个对象的访问.用在:在某些情况下,一个客户不想或者不能直接访问另一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用,代理对象还可以完成它附加的操作. 例子:就像房东.租客.中介的关系.中介(代理对象)为房东(真实对象)出租房子,租客(客户)通过中介(代理对象)来找房子租房子,中介完成了租房以后可以收取中介费(附加操作). 先看看静态代理模式,通过上面对代理模式的理解,可以了解到代理模式:即不直接通过new一个真实对象来调用方法,而是通过代理对象来

  • 代理模式:JAVA静态代理和动态代理的实例和实现详解

    目录 前言 静态代理 实现简述 创建human接口 创建接口实现类 创建针对接口实现增强操作的代理 代理实现效果 动态代理 实现简述 要点:向上转型 创建YoungMan接口 创建两个接口实现类 创建动态代理实例对象 代理实现效果 要点:InvocationHandler补充 代理模式和修饰模式的区别 总结 前言 代理模式,我们这里结合JAVA的静态代理和动态代理来说明,类比Spring AOP面向切面编程:增强消息,也是代理模式. 而我们的静态代理和动态代理,与(service)接口和(ser

  • Java的动态代理和静态代理详解

    目录 0.代理模式 1.静态代理 2.加深理解 3.动态代理 动态代理的例子 总结 0.代理模式 为什么要学习代理模式?这是SpringAOP的底层[SpringAOP和SpringMVC] 代理模式的分类: 静态代理 动态代理 1.静态代理 静态代理中,我们对目标对象的每个方法的增强都是手动完成的(后面会具体演示代码_),非常不灵活(比如接口一旦新增加方法,目标对象和代理对象都要进行修改)且麻烦(_需要对每个目标类都单独写一个代理类). 实际应用场景非常非常少,日常开发几乎看不到使用静态代理的

  • Java动态代理和反射机制详解

    反射机制 Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法.属性和构造方法等. 动态代理:分为JDK动态代理.cglib动态代理(spring中的动态代理). 静态代理 预先(编译期间)确定了代理者与被代理者之间的关系,也就是说,若代理类在程序运行前就已经存在了,这种情况就叫静态代理 动态代理 代理类在程序运行时创建的代理方式.也就是说,代理类并不是在Java代码中定义的,而是在运行期间根据我们在Java代码中的"指示"动态生成的. 动态代理比

  • 浅谈Java代理(jdk静态代理、动态代理和cglib动态代理)

    一.代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强.加入一些非业务性代码,比如事务.日志.报警发邮件等操作. 二.jdk静态代理 1.业务接口 /** * 业务接口 * @author pc * */ public interface UserService { // 增加一个用户 public void addUser(); // 编辑账户 public void editUser(); } 2.业务实现类 /** * 业务实现类 * @author pc

  • 深入理解Java动态代理与静态代理

    目录 前言 一.静态代理 静态代理的使用 与装饰者模式的区别 二.动态代理 JDK 动态代理 CGlib 动态代理实现 前言 学习 Spring 的过程中,不可避免要掌握代理模式.这篇文章总结一下代理模式.顾名思义,代理,就是你委托别人帮你办事,所以代理模式也有人称作委托模式的.比如领导要做什么事,可以委托他的秘书去帮忙做,这时就可以把秘书看做领导的代理.下面将以这个例子来讲解.代理模式又分为静态代理和动态代理. 一.静态代理 静态代理的使用 静态代理,代理类和被代理的类实现了同样的接口,代理类

  • java 代理机制的实例详解

    java 代理机制的实例详解 前言: java代理分静态代理和动态代理,动态代理有jdk代理和cglib代理两种,在运行时生成新的子类class文件.本文主要练习下动态代理,代码用于备忘.对于代理的原理和机制,网上有很多写的很好的,就不班门弄斧了. jdk代理 实例代码 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; publi

  • Java实现多线程中的静态代理模式

    前言 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能. 简言之,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式. 静态代理属于设计模式中的代理模式.反之则有动态代理,本篇文章不展开讲,有兴趣的可自行谷歌研究研究. 其实继承Thread也属于静态代理的一种,所以在这里学习静态代理有助于我们学习多线程. 静态代理 优点:可以在不修改目标对象的前提下扩

  • Java代理模式的示例详解

    目录 定义 案例 需求 方案:静态代理模式 总结 定义 代理模式(Proxy Parttern) 为一个对象提供一个替身,来控制这个对象的访问,即通过代理对象来访问目标对象,这样做的话好处是可以在目标对象实现的基础上,进行额外的功能的扩展. 案例 需求 苹果公司通过苹果代理商来卖手机 方案:静态代理模式 定义抽象接口类,该类在代理模式中扮演的是一个抽象功能的角色,该案例中就是把出售手机抽象为了一个接口 /** * 售卖手机的接口(代理模式--抽象角色) * @author:liyajie * @

  • Python3爬虫关于代理池的维护详解

    我们在上一节了解了代理的设置方法,利用代理我们可以解决目标网站封 IP 的问题,而在网上又有大量公开的免费代理,其中有一部分可以拿来使用,或者我们也可以购买付费的代理 IP,价格也不贵.但是不论是免费的还是付费的,都不能保证它们每一个都是可用的,毕竟可能其他人也可能在用此 IP 爬取同样的目标站点而被封禁,或者代理服务器突然出故障或网络繁忙.一旦我们选用了一个不可用的代理,势必会影响我们爬虫的工作效率. 所以说,在用代理时,我们需要提前做一下筛选,将不可用的代理剔除掉,保留下可用代理,接下来在获

  • Nginx 代理与负载均衡详解

    Nginx 代理与负载均衡详解 nginx除了可以做网站的虚拟主机之外,还可以做代理器,并且, nginx在代理器的基础上可以做到负载均衡.  一.代理器: 所谓代理器,即接受请求,将请求进行转发,得到结果然后返回. 比如,我访问localhost:10010的时候nginx代理到百度的页面.   nginx实现代理: server { listen 10010; server_name localhost; location / { proxy_pass http://www.baidu.co

  • Vue多环境代理配置方法思路详解

    背景: 多人协作模式下,修改代理比较麻烦,而且很容易某个开发人员会修改了vue.config.js文件后提交了. 第一,很容易引起冲突. 第二,很容易出现代理错误,需要排查.而且现在微服务盛行,在生产环境下有网关配置,不会出错,但是在本地调试会造成麻烦,如修改了代理地址需要同步修改代理中的地址,很麻烦也很容易出错. 解决思路: 1.开发中定义常量js文件,例如constants.js.用户存放各个服务需要代理的服务名. let api = "" let loginServer = &q

随机推荐