代理设计模式-Proxy

设计模式—proxy

什么是代理

增强一个对象的功能
买火车票,app就是一个代理,他代理了火车站,小区当中的代售窗口
java当中如何实现代理

java实现的代理的两种办法
代理的名词
代理对象 增强后的对象
目标对象 被增强的对象
他们不是绝对的,会根据情况发生变化

静态代理

继承 :代理对象继承目标对象,重写需要增强的方法;
            缺点:会代理类过多,非常复杂
聚合: 目标对象和代理对象实现同一个接口,代理对象当中要包含目标对象。
            缺点:也会产生类爆炸,只不过聚合比继承少一点点

总结:如果在不确定的情况下,尽量不要去使用静态代理。因为一旦你写代码,就会产生类,一旦产生类就爆炸。

动态代理

自己模拟的动态代理
不需要手动创建类文件(因为一旦手动创建类文件,就会产生类爆炸),通过接口反射生成一个类文件,然后调用第三方的编译技术,动态编译这个产生的类文件成class文件,继而利用UrlclassLoader(因为这个动态产生的class不在工程当中所以需要使用UrlclassLoader)把这个动态编译的类加载到jvm当中,最后通过反射把这个类实例化。
缺点:首先要生成文件
缺点:动态编译文件 class
缺点:需要一个URLclassloader
软件性能的最终体现在IO操作

JDK动态代理

通过接口反射得到字节码,然后把字节码转成class native openJDK c++
在自己模拟的动态代理中,代理逻辑是写死的,那么怎么让代理逻辑动态呢?

  1. 思考点1:将代理逻辑的方法传进来,传进来后怎么调用呢?method.invoke(object,args)么?注意一点,我们只是在newProxyInstance(Object
    object)中去生成了代理类的源文件Xxx.java,
    并不是通过newProxyInstance去调用了method.invoke。代理类中被调用是在原方法调用时,可是在调用原方法时我们并不会传入Method类型的参数。代理方法和目标方法的参数时一致的,不可能代理中多传入其他参数。因此,代理逻辑只能是在生成代理的类的过程中确定好,即所需要的的一切,必须通过newProxyInstance(Object
    object)中传入,而此方法中又不能传入method,因为即使传入了,在代理源文件中它只是一堆字符串,并没有实际的对象,因此我们传入一个对象,就是我们自己实现InvocationHandler接口的实现类的对象。

    思考点2:我们自己写的InvocationHandler的实现类的重写的方法里,包含了代理逻辑和目标逻辑,如何调用目标逻辑呢?就必须有目标对象和目标方法,即MyInvocationHandler类初始化时必须串入要代理的类的对象,而且invoke()方法必须能拿到目标方法名。怎么拿到呢?

    思考点3:代理方法中最终调用MyInvocationHandler重写的invoke(Object proxy, Method
    method, Object[] args)方法,则需要传入这么多参数,那说明代理类中也必须能拿到这些参数呀?怎么或许到呢?
    按理来说,目标对象proxy是不需要传入的呢?

下面就带着这三个问题,看看JDK动态代理时如何实现的上面的问题的。下面我们称代理类为$Proxy,看下面代码,它是代理某个类生成的源文件

package com.google;
import com.dao.Dao;
import com.luban.dao.CoustomInvocationHandler;
import java.lang.Exception;
import java.lang.reflect.Method;
public class $Proxy implements Dao {
    private InvocationHandler h;

    // InvocationHandler是我们手写的InvocationHandler的实现类
    public $Proxy (InvocationHandler h){
        this.h =h;
    }

    public void query()throws Exception {
        // 此method对象是生成本类源码的代码中根据接口的class对象获得的,方法的参数也是如此
        Method method = Class.forName("com.dao.Dao").getDeclaredMethod("query");

        // 调用这的invoke,invoke里面包含代理逻辑和目标逻辑。jdk动态代理中是需要传入目标对象,方法,和方法参数的。后两者都能解决了,那么
        return (void)h.invoke(method);
    }
}

下面查看我们自己的InvocationHandler的实现类:

package com.handler;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


public class MyInvocationHandler implements InvocationHandler {
    private Object target;


    public MyInvocationHandler(Object target){
        this.target=target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理逻辑");
        return method.invoke(target,args);
    }
}

jdk动态代理为什么不使用继承?

因为jdk动态代理的代理对象继承了一个Proxy类,而java是单继承语言,所以代理没有使用继承。jdk动态代理底层,通过接口反射获取到字节码,然后通过native的方法将字节码转换成对象。

cglib

asm是操作字节码的开源框架。cglib就是基于继承,使用asm技术实现。
clazz.newInstance()调用的是默认的构造方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java设计模式是一组经过实践验证的面向对象设计原则和模式,可以帮助开发人员解决常见的软件设计问题。下面是常见的23种设计模式: 1. 创建型模式(Creational Patterns): - 工厂方法模式(Factory Method Pattern) - 抽象工厂模式(Abstract Factory Pattern) - 单例模式(Singleton Pattern) - 原型模式(Prototype Pattern) - 建造者模式(Builder Pattern) 2. 结构型模式(Structural Patterns): - 适配器模式(Adapter Pattern) - 桥接模式(Bridge Pattern) - 组合模式(Composite Pattern) - 装饰器模式(Decorator Pattern) - 外观模式(Facade Pattern) - 享元模式(Flyweight Pattern) - 代理模式(Proxy Pattern) 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility Pattern) - 命令模式(Command Pattern) - 解释器模式(Interpreter Pattern) - 迭代器模式(Iterator Pattern) - 中介者模式(Mediator Pattern) - 备忘录模式(Memento Pattern) - 观察者模式(Observer Pattern) - 状态模式(State Pattern) - 策略模式(Strategy Pattern) - 模板方法模式(Template Method Pattern) - 访问者模式(Visitor Pattern) 4. 并发型模式(Concurrency Patterns): - 保护性暂停模式(Guarded Suspension Pattern) - 生产者-消费者模式(Producer-Consumer Pattern) - 读写锁模式(Read-Write Lock Pattern) - 信号量模式(Semaphore Pattern) - 线程池模式(Thread Pool Pattern) 这些设计模式可以根据问题的特点和需求来选择使用,它们提供了一些可复用的解决方案,有助于开发高质量、可维护且易于扩展的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值