代理模式(Java实现)

这篇具有很好参考价值的文章主要介绍了代理模式(Java实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

代理模式是常见的设计模式之一,顾名思义,代理模式就是代理对象具备真实对象的功能,并代替真实对象完成相应操作,并能够在操作执行的前后,对操作进行增强处理。(为真实对象提供代理,然后供其他对象通过代理访问真实对象)

分为

  • 静态代理

  • 动态代理

    • jdk动态代理

    • cglib动态代理

静态代理

真实类和代理类要实现同一个接口,在代理类中实现真实类的方法同时可以进行真实类方法的增强处理,在一个代理类中就可以完成对多个真实对象的注入工作。

public interface IRentHouse {
    void rentHouse();
}
public class RentHouse implements IRentHouse {

    @Override
    public void rentHouse() {
        System.out.println("实现租房");
    }
}
public class IntermediaryProxy implements IRentHouse {
    private IRentHouse iRent;
    public IntermediaryProxy(IRentHouse iRentHouse) {
        iRent=iRentHouse;
    }
    @Override
    public void rentHouse() {
        System.out.println("交中介费");
        iRent.rentHouse();
        System.out.println("中介负责维修管理");
    }
}
//client测试类
public class TestStaticProxy {
    public static void main(String[] args) {
        //定义租房
        IRentHouse iRentHouse = new RentHouse();
        //定义中介
        IRentHouse intermediaryProxy = new IntermediaryProxy(iRentHouse);
        //中介租房
        intermediaryProxy.rentHouse();
    }
}

动态代理

从静态代理的代码中可以发现,静态代理的缺点显而易见,那就是当真实类的方法越来越多的时候,这样构建的代理类的代码量是非常大的,所以就引进动态代理.

动态代理允许使用一种方法的单个类(代理类)为具有任意数量方法的任意类(真实类)的多个方法调用提供服务

JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 java 语言的反射机制。

jdk动态代理(接口代理)

Jdk代理涉及到java.lang.reflect包中的InvocationHandler接口和Proxy类,核心方法是

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 

jdk动态代理过程中实际上代理的是接口,是因为在创建代理实例的时候,依赖的是java.lang.reflect包中Proxy类的newProxyInstance方法,该方法的生效就恰恰需要这个参数;

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{
        ……
}

下面以案例来说明jdk动态代理的完整过程:

//接口
public interface Person {
    void wakeup();
    void sleep();
}
//实现类1
public class Student implements Person{
    private String name;
    public Student() {
    }
    public Student(String name) {
        this.name = name;
    }
    @Override
    public void wakeup() {
        System.out.println("学生"+name+"早晨醒来啦");
    }
    @Override
    public void sleep() {
        System.out.println("学生"+name+"晚上睡觉啦");
    }
}
//代理类
public class JDKDynamicProxy implements InvocationHandler {
    private Object bean;
    public JDKDynamicProxy(Object bean) {
        this.bean=bean;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodname=method.getName();
        if (methodname.equals("wakeup")){
            System.out.println("早安~~~");
        }else if(methodname.equals("sleep")){
            System.out.println("晚安~~~");
        }
        return method.invoke(bean,args);
    }
}
//测试类
public class TestJDKDynamicProxy {
    public static void main(String[] args) {
        JDKDynamicProxy proxy = new JDKDynamicProxy(new Student("张三"));
        //创建代理实例
        Person student = (Person) Proxy.newProxyInstance(proxy.getClass().getClassLoader(), new Class[]{Person.class}, proxy);
        student.wakeup();
        student.sleep();
    }
}

输出结果为

早安~~
学生张三早晨醒来啦
晚安~~
学生张三晚上睡觉啦
接口中的方法,以及代理类中重写的invoke方法,但是invoke()方法并不是显式调用的,是在创建代理实例的过程中生成的接口虚拟代理类中调用了invoke方法。(把Sproxy0的实例强制转换成对应接口类型的引用,然后执行接口方法,进而执行代理类中invoke ()) 

总结对比:

1.静态代理中,代理类和真实类实现的是同一个接口,重写同样的方法;jdk动态代理中,代理类和真实类关系不大,代理类实现无侵入式的代码扩展。

2.静态代理中当接口中方法增加的时候,在代理类代码量也会增加,显然是不妥的;jdk动态代理解决了这个问题,当业务增加,代理类的代码不会增加。

3.jdk动态代理实现的是jdk自带InvocationHandler接口,实现了这个接口的类也叫拦截器类,也叫代理类。

cglib动态代理

从上面可以看出,jdk动态代理的前提条件是,要有接口存在,那还有许多场景是没有接口的,这个时候就需要cglib动态代理了,CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。cglib动态代理过程中生成的是实现类的子类,cglib是如何凭空创造的实现类的子类的,下面是测试代码

//所需的代理类
public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer=new Enhancer();
    private Object bean;

    public CglibProxy(Object bean) {
        this.bean = bean;
    }

    public Object getProxy(){
        //设置需要创建子类的类
        enhancer.setSuperclass(bean.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        String methodName = method.getName();
        if (methodName.equals("wakeup")){
            System.out.println("早安~~~");
        }else if(methodName.equals("sleep")){
            System.out.println("晚安~~~");
        }
        return method.invoke(bean,objects);
    }
}
//测试类
public class TestCglibProxy {
    public static void main(String[] args) {
        //生成虚拟代理类的代码,本来虚拟代理子类是看不见的,
        //下面这句话的作用就是把执行过程中cglib增强后的class字节码文件
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\aop");
        CglibProxy proxy = new CglibProxy(new Cat("咪咪"));
        Cat cat = (Cat) proxy.getProxy();
        cat.wakeup();
        cat.sleep();
    }
}

总结:

cglib动态代理和jdk动态代理的区别显而易见,但是实现逻辑差不多,cglib代理类是通过实现MethodInterceptor,重写intercept方法,通过生成被代理类的子类来达到代理增强代码的目的;而Jdk代理是通过实现InvocationHandler,重写invoke方法,通过生成接口的代理类来达到代码增强的目的,所以jdk动态代理的实现需要接口,cglib则不需要,spring5.0以上以及springboot2.0以上默认采用cglib动态来实现AOP。文章来源地址https://www.toymoban.com/news/detail-653946.html

到了这里,关于代理模式(Java实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java代理模式——静态代理与动态代理

    代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。 可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对象的功能,这个替身也可以为被

    2024年02月13日
    浏览(47)
  • Java设计模式(十三)代理模式

    一、概述 代理模式是一种结构型设计模式,它提供了一个代理对象,充当被代理对象的接口,以控制对被代理对象的访问。代理模式可以在不修改被代理对象的情况下,增加额外的功能或控制访问方式。 二、代码 以下是一个示例代码,说明代理模式的使用: 在上述代码中,

    2024年02月04日
    浏览(41)
  • 【Java设计模式005】代理模式

    由于一些特定原因某些对象不适合或者不能直接引用目标对象,这时就可以使用代理模式。代理模式为目标对象提供一个代理以控制访问对象对目标对象的访问。客户端只能直接访问代理对象,不能直接访问目标对象,这么做确保了目标对象的安全。生活中一个常见的例子就

    2024年02月12日
    浏览(41)
  • 基于Java的设计模式 - 代理模式

    代理模式是一种使用代理对象来执行目标对象的方法并在代理对象中增强目标对象方法的一种设计模式。简单来讲就是在不修改目标对象的基础上,增强主业务逻辑的设计模式。 代理模式基本可分为三种 静态代理 JDK动态代理 CGLIB动态代理 上述简单分就是静态和动态代理,静

    2024年02月07日
    浏览(37)
  • Java 与设计模式(13):代理模式

    代理模式是一种结构型设计模式,用于在访问对象时引入一个代理对象,以控制对实际对象的访问。代理对象充当了客户端和实际对象之间的中介,客户端通过代理对象间接地访问实际对象,从而可以在访问过程中添加额外的逻辑或控制。代理模式可以提供对实际对象的保护

    2024年02月09日
    浏览(38)
  • Java设计模式---单例 工厂 代理模式

    单例模式是设计模式中的一种,属于创建型模式。在软件工程中,单例模式确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于那些需要频繁实例化然后引用,且创建新实例的开销较大的类,例如数据库连接池、缓存管理等。 意图 :保证一个类仅有一个实例

    2024年01月24日
    浏览(52)
  • 代理模式(java)

    目录 结构 静态代理案例  代码实现 售票类 火车站类 代理类 测试类 优缺点 优点 缺点 代理(Proxy)模式分为三种角色: 抽象主题(Subject)类 : 通过接口或抽象类声明真实主题和代理对象实现的业务方法。 真实主题(Real Subject)类 : 实现了抽象主题中的具体业务,是代理

    2024年02月16日
    浏览(32)
  • java代理模式

    比如现在项目经理有一个需求:在项目现有所有类的方法前后打印日志。如何实现? 静态代理是在编译的时候就将实现类和代理类编程了字节码class文件,然后加载到JVM中。 程序员要手动为每一个目标类编写对应的代理类。如果当前系统已经有成百上千个类,工作量太大了。

    2024年02月13日
    浏览(31)
  • Java 代理模式详解

    本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注博主!也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远! 代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real

    2024年02月06日
    浏览(28)
  • Java中的代理模式

    接口 目标类 代理类 测试 接口 目标类 动态代理类 测试 总结: 动态生成代理类 通过实现接口生成代理类(目标接口必须实现接口) 代理类是实现接口的方式 调用目标类使用反射调用 目标类调用本类方法只会代理一次 目标类 代理类 测试 总结 通过ASM第三方框架动态代理 无需接

    2024年02月15日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包