当前位置: 首页 > article >正文

代理模式 JAVA

文章目录

    • 涉及的JAVA语言特性
    • 接口和转型
      • 接口(Interface)
        • 接口的特点:
        • 示例代码:
      • 转型(类型转换)
        • 接口与转型的关系
        • 多态与接口的结合
      • 总结
    • UML
    • 代理模型
    • 动态代理模式
    • Springboot项目中遇到的代理模式

涉及的JAVA语言特性

  1. 接口(Interfaces):

    • 在JDK动态代理中,Subject接口定义了代理类和真实类共同实现的方法。
    • InvocationHandler接口是JDK动态代理机制的核心,用于定义代理对象的行为。
    • 在CGLIB中,MethodInterceptor接口用于定义拦截方法。
  2. 反射(Reflection):

    • JDK动态代理heavily依赖反射机制。
    • Method.invoke()方法用于在运行时调用目标对象的方法。
    • Proxy.newProxyInstance()方法使用反射创建代理类的实例。
  3. 动态类生成:

    • JDK动态代理在运行时动态生成代理类。
    • CGLIB通过字节码生成技术在运行时创建目标类的子类。
  4. 泛型(Generics):

    • 虽然在给定的代码中没有显式使用,但Proxy.newProxyInstance()方法内部使用了泛型。
  5. 多态(Polymorphism):

    • 代理对象可以被当作接口类型使用,展示了多态性。
  6. 内部类:

    • DynamicProxyHandlerCglibProxyInterceptor可以被实现为内部类,以更好地封装代理逻辑。
  7. 异常处理:

    • invokeintercept方法都声明了throws Throwable,表明它们使用了Java的异常处理机制。
  8. 面向对象编程(OOP):

    • 整个设计展示了封装、继承和多态等OOP概念。
  9. 方法重写(Method Overriding):

    • DynamicProxyHandler重写了invoke方法。
    • CglibProxyInterceptor重写了intercept方法。
  10. 类加载器(ClassLoader):

    • JDK动态代理使用类加载器来加载动态生成的代理类。
  11. 注解(Annotations):

    • @Override注解用于invokeintercept方法,虽然在给定代码中没有显示。
  12. 可变参数(Varargs):

    • Method.invoke()MethodProxy.invokeSuper()方法内部使用了可变参数。
  13. 字节码操作:

    • CGLIB通过操作字节码来创建代理类,虽然这主要是库内部实现的细节。
  14. 回调(Callbacks):

    • CGLIB使用回调机制来实现方法拦截。

接口和转型

在面向对象编程中,接口和类型转换(转型)是两个非常重要的概念。它们在Java等编程语言中密切相关,尤其是在实现多态性和解耦时。

接口(Interface)

接口是一种抽象类型,定义了一组没有实现的方法。这些方法必须在实现接口的类中提供具体实现。接口主要用于定义类应该具备的行为,而不关注这些行为的具体实现方式。

接口的特点:
  1. 方法无实现:接口中的方法都是抽象的(Java 8之后允许定义默认方法default method和静态方法)。
  2. 多重继承:一个类可以实现多个接口,这在Java中提供了一种方式来模拟多重继承。
  3. 解耦:接口允许程序设计者定义行为标准,不依赖具体的实现。这有助于降低代码的耦合度。
示例代码:
interface Animal {
    void makeSound();  // 定义一个方法,没有实现
}

class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat meows");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myDog.makeSound();  // 输出: Dog barks
        myCat.makeSound();  // 输出: Cat meows
    }
}

解释:在上述代码中,Animal是一个接口,定义了一个方法makeSound()DogCat类实现了Animal接口,并提供了各自的具体实现。通过接口引用,我们可以以统一的方式操作不同的对象(例如DogCat),这是多态性的一个重要体现。

转型(类型转换)

转型指的是将一个对象的引用从一种类型转换为另一种类型。在与接口相关的转型中,主要涉及的是向上转型(Upcasting)和向下转型(Downcasting)。

接口与转型的关系
  1. 向上转型(Upcasting)

    • 当一个类实现了某个接口时,可以将该类的对象转型为该接口的引用。这种转换是自动的,不需要强制类型转换。
    Animal myDog = new Dog();  // 向上转型,自动进行
    

    解释:这里Dog对象被赋给Animal接口的引用。由于Dog类实现了Animal接口,所以这是一种安全的操作,并且是自动进行的。向上转型后,你只能通过Animal接口调用接口中定义的方法,而无法调用Dog类中的其他方法。

  2. 向下转型(Downcasting)

    • 如果你需要访问子类中特有的方法,必须将接口类型的引用向下转型为具体的实现类类型。这种转换需要显式的强制类型转换。
    Animal myAnimal = new Dog();
    Dog myDog = (Dog) myAnimal;  // 向下转型,需要强制转换
    myDog.bark();  // 调用子类特有的方法
    

    解释:在上面的例子中,myAnimal最初是一个Animal接口类型的引用,但实际上它指向的是一个Dog对象。如果需要调用Dog类中特有的方法(如bark()),必须将myAnimal向下转型为Dog类型。这种转换必须显式地进行,并且在运行时,如果myAnimal不是Dog对象,可能会抛出ClassCastException异常。

多态与接口的结合

通过结合接口和转型,你可以实现多态性。多态性允许同一个接口以不同的形式表现出来,这使得代码更为灵活和可扩展。

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = getAnimal();  // 假设这个方法返回Animal的某个实现
        myAnimal.makeSound();  // 多态调用,根据具体类型执行对应方法

        if (myAnimal instanceof Dog) {
            Dog myDog = (Dog) myAnimal;  // 向下转型
            myDog.bark();  // 调用子类特有方法
        }
    }

    public static Animal getAnimal() {
        // 返回某个Animal的实现
        return new Dog();  // 可能是Dog,Cat等任一实现
    }
}

解释:在这个示例中,getAnimal()方法返回一个Animal接口的实现。根据返回的具体实现类型,可以使用向下转型来访问特有的方法。instanceof操作符可以用来检查对象的真实类型,以确保向下转型的安全性。

总结

  • 接口定义了行为的规范,而不关心具体实现。它们是实现多态性和解耦的重要工具。
  • 向上转型是将子类对象赋给父类或接口类型引用的过程,是自动的。
  • 向下转型是将父类或接口类型的引用强制转换为子类类型引用的过程,必须显式进行,并且存在类型安全风险。

UML

代理模型

动态代理模式

Springboot项目中遇到的代理模式


http://www.kler.cn/news/289678.html

相关文章:

  • 同物种,不同版本之间的坐标转化
  • 基于SSM+Vue+MySQL的高校课程评价管理系统
  • YUM配置文件开启缓存
  • Java 基于微信小程序的小区服务管理系统,附源码
  • 【STM32+HAL库】---- 通用定时器实现外部脉冲计数
  • 力扣45-跳跃游戏II (java详细题解)
  • 图文解析保姆级教程: IDEA里面创建SpringBoot工程、SpringBoot项目的运行和测试、实现浏览器返回字符串
  • git查看代码提交记录
  • 【C++题解】1002 - 编程求解1+2+3+...+n
  • 【系统架构设计师】论文:论面向服务的架构设计及其应用
  • Vue3其他Api
  • 2024.9.3 Python,二分查找解决在D天内送达包裹的能力,dfs二叉树的层平均值,动态规划二分查找贪心算法解决最长增长子序列和马戏团人塔
  • 第66期 | GPTSecurity周报
  • 无线信道中ph和ph^2的场景
  • gitee 简单使用
  • Storm AI : 最佳长文写作工具
  • 精准设计与高效开发:用六西格玛设计DFSS实现新能源汽车开发突破
  • 解除本地Git仓库与远程仓库关联
  • 【系统架构设计师-2021年】综合知识-答案及详解
  • 卷积神经网络(Datawhale X 李宏毅苹果书AI夏令营)
  • 宝贝甜梦秘籍!康姿百德柔压磁性枕豪华款守护成长每一夜
  • 车辆违停智能监测摄像头
  • 【maxcompute|ODPS|SQL|HSQL】日期数据非标准日期格式(yyyy/M/d),如何转为yyyy-MM-dd HH:mm:ss标准格式
  • ArcGIS Pro SDK (十二)布局 8 布局元素选择和更改
  • 【K8s】专题十三:Kubernetes 容器运行时之 Docker 与 Containerd 详解
  • Vue2的学习1
  • 配置管理 —— SpringCloud Config
  • CSS - 搜索框小动效
  • 重头开始嵌入式第三十二天(TCP多客户端模型)
  • 文件包含PHP伪协议利用方法