代理模式 JAVA

文章目录

涉及的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. 解耦:接口允许程序设计者定义行为标准,不依赖具体的实现。这有助于降低代码的耦合度。
示例代码:
java 复制代码
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)

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

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

  2. 向下转型(Downcasting)

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

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

多态与接口的结合

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

java 复制代码
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项目中遇到的代理模式

相关推荐
serve the people几秒前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端
qmx_071 小时前
HTB-Jerry(tomcat war文件、msfvenom)
java·web安全·网络安全·tomcat
为风而战1 小时前
IIS+Ngnix+Tomcat 部署网站 用IIS实现反向代理
java·tomcat
编程零零七2 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
技术无疆3 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
2401_858286113 小时前
52.【C语言】 字符函数和字符串函数(strcat函数)
c语言·开发语言
铁松溜达py3 小时前
编译器/工具链环境:GCC vs LLVM/Clang,MSVCRT vs UCRT
开发语言·网络
everyStudy3 小时前
JavaScript如何判断输入的是空格
开发语言·javascript·ecmascript
C-SDN花园GGbond5 小时前
【探索数据结构与算法】插入排序:原理、实现与分析(图文详解)
c语言·开发语言·数据结构·排序算法
迷迭所归处6 小时前
C++ —— 关于vector
开发语言·c++·算法