专业的JAVA编程教程与资源

网站首页 > java教程 正文

代理模式(剪映怎么打开代理模式)

temp10 2024-10-24 17:23:23 java教程 14 ℃ 0 评论

代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,它允许通过代理对象控制对原始对象的访问。代理模式创建一个代理对象,使代理对象可以在不改变原始对象的情况下,控制客户端的访问。代理对象通常是原始对象的包装器,它提供了与原始对象相同的接口,并且在调用原始对象的方法之前或之后可以执行一些附加操作。

代理模式有多种变体,其中最常见的有以下几种:

代理模式(剪映怎么打开代理模式)

  1. 静态代理:在编译时确定代理对象,并在代理对象中显式实现原始对象的接口。
  2. 动态代理:在运行时使用反射机制动态创建代理对象,并代理对象的方法调用将被转发到原始对象。
  3. 远程代理:在不同的进程或计算机上,使用网络通信来访问远程对象。
  4. 虚拟代理:在需要时才实例化原始对象,以避免在创建时进行大量初始化工作。
  5. 智能代理:在代理对象中添加一些额外的功能,如缓存、事务处理、权限检查等。

代理模式的优点包括:

  1. 代理对象可以在不修改原始对象的情况下,增强原始对象的功能。
  2. 代理对象可以控制对原始对象的访问,以实现访问控制、缓存等功能。
  3. 代理对象可以隐藏原始对象的实现细节,保护原始对象的安全性。
  4. 代理对象可以在原始对象不可用时,提供一个占位符对象。

代理模式的缺点包括:

  1. 代理模式会增加系统的复杂性,因为需要额外的代理对象来管理原始对象。
  2. 代理模式可能会降低系统的性能,因为在代理对象中添加了额外的逻辑和处理。
  3. 代理模式可能会增加代码的维护难度,因为需要维护原始对象和代理对象之间的一致性。

手写静态代理

静态代理是在编译时就已经确定了代理类和委托类的关系,并生成了代理类的字节码文件,代理类和委托类的关系在程序运行之前就已经确定了。

以下是一个简单的Java静态代理示例,演示如何创建一个代理类:

  1. 定义接口
public interface Calculator {
    int add(int a, int b);
}
  1. 实现接口
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}
  1. 创建代理类
public class CalculatorProxy implements Calculator {
    private Calculator calculator;

    public CalculatorProxy(Calculator calculator) {
        this.calculator = calculator;
    }

    @Override
    public int add(int a, int b) {
        System.out.println("Before calculation...");
        int result = calculator.add(a, b);
        System.out.println("After calculation...");
        return result;
    }
}

在上面的代码中,CalculatorProxy是代理类,实现了Calculator接口,并包含了一个Calculator类型的成员变量calculator。代理类的构造函数接受一个Calculator类型的参数,该参数是委托类的实例。

代理类的add()方法调用了委托类的add()方法,并在方法调用前后添加了一些额外的逻辑。

  1. 使用代理类
public static void main(String[] args) {
    Calculator calculator = new CalculatorImpl();
    Calculator proxy = new CalculatorProxy(calculator);

    int result = proxy.add(1, 2);
    System.out.println("Result: " + result);
}

在上面的代码中,首先创建一个CalculatorImpl的实例,然后通过该实例创建一个CalculatorProxy的实例,代理类的构造函数接受委托类的实例作为参数。

最后,使用代理对象调用add()方法,代理类的add()方法中会先输出一条“Before calculation...”的日志,然后调用委托类的add()方法,最后输出一条“After calculation...”的日志。

这就是一个简单的Java静态代理示例。通过代理对象,我们可以在不修改委托类的情况下,为委托类的方法添加额外的逻辑。静态代理虽然简单易用,但缺点是需要手动编写代理类,当委托类的方法发生变化时,代理类也需要相应地进行修改。

手写动态代理

Java动态代理是在运行时动态地生成代理类的字节码,并在内存中创建代理类的实例。与静态代理不同的是,动态代理可以代理任意实现了接口的委托类,而不需要为每个委托类手动编写代理类。

下面是一个简单的Java动态代理示例,演示如何创建一个代理类:

  1. 定义接口
public interface Calculator {
    int add(int a, int b);
}
  1. 实现接口
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
}
  1. 创建代理类
public class CalculatorProxy implements InvocationHandler {
    private Object target;

    public CalculatorProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before calculation...");
        Object result = method.invoke(target, args);
        System.out.println("After calculation...");
        return result;
    }
}

在上面的代码中,CalculatorProxy实现了Java标准库中的InvocationHandler接口,它的invoke()方法会在代理对象调用方法时被调用,方法参数中包含了委托类的实例、委托方法的信息以及方法参数。在该方法中,可以添加额外的逻辑,并调用委托类的方法。

  1. 使用代理类
public static void main(String[] args) {
    Calculator calculator = new CalculatorImpl();
    Calculator proxy = (Calculator) Proxy.newProxyInstance(
            calculator.getClass().getClassLoader(),
            calculator.getClass().getInterfaces(),
            new CalculatorProxy(calculator));

    int result = proxy.add(1, 2);
    System.out.println("Result: " + result);
}

在上面的代码中,首先创建一个CalculatorImpl的实例,然后通过Java标准库中的Proxy.newProxyInstance()方法创建一个代理类的实例。该方法接受三个参数,分别是类加载器、接口列表和InvocationHandler实例。通过该方法返回的代理对象,可以调用委托类的方法,并在方法调用前后添加额外的逻辑。

这就是一个简单的Java动态代理示例。通过动态代理,我们可以代理任意实现了接口的委托类,并为委托类的方法添加额外的逻辑。相比静态代理,动态代理的缺点是性能较低,因为需要在运行时动态生成代理类的字节码。但是,由于动态代理的灵活性和通用性,它在很多场景下都是非常有用的。

cglib实现动态代理

除了使用Java标准库中的Proxy类实现动态代理外,还可以使用第三方库CGLIB实现动态代理。CGLIB是一个高效的字节码生成库,它可以在运行时动态生成代理类的字节码,从而实现动态代理。与Java标准库中的动态代理不同,CGLIB可以代理非接口类型的类。

下面是一个使用CGLIB实现动态代理的简单示例:

  1. 引入依赖
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
  1. 定义目标类
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}
  1. 创建代理类
public class CalculatorProxy implements MethodInterceptor {
    private Object target;

    public CalculatorProxy(Object target) {
        this.target = target;
    }

    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("Before calculation...");
        Object result = method.invoke(target, args);
        System.out.println("After calculation...");
        return result;
    }
}

在上面的代码中,CalculatorProxy实现了CGLIB的MethodInterceptor接口,它的intercept()方法会在代理对象调用方法时被调用,方法参数中包含了委托方法的信息以及方法参数。在该方法中,可以添加额外的逻辑,并调用委托类的方法。

  1. 使用代理类
public static void main(String[] args) {
    Calculator calculator = new Calculator();
    Calculator proxy = (Calculator) new CalculatorProxy(calculator).getProxy();

    int result = proxy.add(1, 2);
    System.out.println("Result: " + result);
}

在上面的代码中,首先创建一个Calculator的实例,然后通过调用CalculatorProxy的getProxy()方法创建一个代理类的实例。在该方法中,使用CGLIB的Enhancer类动态生成代理类的字节码,并设置代理类的父类和回调方法。通过该方法返回的代理对象,可以调用委托类的方法,并在方法调用前后添加额外的逻辑。

这就是一个简单的使用CGLIB实现动态代理的示例。与Java标准库中的动态代理相比,CGLIB可以代理非接口类型的类,并且性能较高,但它也有一些缺点,例如不能代理final方法和类等。在实际开发中,可以根据实际情况选择使用Java标准库中的动态代理或CGLIB。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表