Java的代理模式怎么理解

发布时间:2022-03-29 15:35:45 作者:iii
来源:亿速云 阅读:117

Java的代理模式怎么理解

1. 代理模式概述

代理模式(Proxy Pattern)是Java中一种常用的设计模式,属于结构型模式。它通过创建一个代理对象来控制对原始对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以在不改变原始对象的情况下,增加额外的功能或控制访问。

1.1 代理模式的作用

1.2 代理模式的分类

在Java中,代理模式主要分为以下几种类型:

2. 静态代理

静态代理是最简单的代理模式,它要求代理类和目标类实现相同的接口或继承相同的父类。代理类在编译时就已经确定,因此称为静态代理。

2.1 静态代理的实现步骤

  1. 定义接口:首先定义一个接口,代理类和目标类都需要实现这个接口。
  2. 实现目标类:目标类是实现接口的具体类,它包含了实际的业务逻辑。
  3. 实现代理类:代理类也实现相同的接口,并在内部持有目标类的引用。代理类可以在调用目标类的方法前后增加额外的逻辑。
  4. 客户端使用代理类:客户端通过代理类来访问目标类,而不是直接访问目标类。

2.2 静态代理的代码示例

// 1. 定义接口
interface Subject {
    void request();
}

// 2. 实现目标类
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

// 3. 实现代理类
class ProxySubject implements Subject {
    private RealSubject realSubject;

    public ProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("ProxySubject: Before handling request.");
        realSubject.request();
        System.out.println("ProxySubject: After handling request.");
    }
}

// 4. 客户端使用代理类
public class StaticProxyDemo {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        ProxySubject proxySubject = new ProxySubject(realSubject);
        proxySubject.request();
    }
}

2.3 静态代理的优缺点

优点: - 简单易懂,容易实现。 - 可以在不修改目标类的情况下,增加额外的功能。

缺点: - 代理类和目标类需要实现相同的接口或继承相同的父类,导致代码冗余。 - 如果接口发生变化,代理类和目标类都需要修改。 - 每个目标类都需要一个对应的代理类,导致类的数量增加。

3. 动态代理

动态代理是在运行时动态生成代理类,代理类不需要实现目标类的接口或继承目标类的父类,而是通过反射机制动态生成代理对象。Java中提供了两种动态代理的实现方式:基于接口的动态代理和基于类的动态代理。

3.1 基于接口的动态代理

Java中的java.lang.reflect.Proxy类提供了基于接口的动态代理实现。通过Proxy.newProxyInstance()方法可以动态生成代理对象。

3.1.1 基于接口的动态代理的实现步骤

  1. 定义接口:首先定义一个接口,目标类需要实现这个接口。
  2. 实现目标类:目标类是实现接口的具体类,它包含了实际的业务逻辑。
  3. 实现InvocationHandler接口InvocationHandler接口是动态代理的核心,它定义了代理对象的方法调用逻辑。在invoke()方法中,可以在调用目标方法前后增加额外的逻辑。
  4. 生成代理对象:通过Proxy.newProxyInstance()方法生成代理对象。
  5. 客户端使用代理对象:客户端通过代理对象来访问目标类,而不是直接访问目标类。

3.1.2 基于接口的动态代理的代码示例

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

// 1. 定义接口
interface Subject {
    void request();
}

// 2. 实现目标类
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

// 3. 实现InvocationHandler接口
class DynamicProxyHandler implements InvocationHandler {
    private Object target;

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

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

// 4. 生成代理对象
public class DynamicProxyDemo {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Subject proxySubject = (Subject) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                new DynamicProxyHandler(realSubject)
        );
        proxySubject.request();
    }
}

3.1.3 基于接口的动态代理的优缺点

优点: - 不需要为每个目标类编写代理类,减少了代码冗余。 - 可以在运行时动态生成代理对象,灵活性高。

缺点: - 只能代理实现了接口的类,无法代理没有实现接口的类。 - 代理对象的生成和调用过程较为复杂,性能开销较大。

3.2 基于类的动态代理

基于类的动态代理通常使用第三方库来实现,例如CGLIB(Code Generation Library)。CGLIB通过继承目标类来生成代理类,因此可以代理没有实现接口的类。

3.2.1 基于类的动态代理的实现步骤

  1. 定义目标类:目标类不需要实现任何接口。
  2. 实现MethodInterceptor接口MethodInterceptor接口是CGLIB的核心,它定义了代理对象的方法调用逻辑。在intercept()方法中,可以在调用目标方法前后增加额外的逻辑。
  3. 生成代理对象:通过CGLIB的Enhancer类生成代理对象。
  4. 客户端使用代理对象:客户端通过代理对象来访问目标类,而不是直接访问目标类。

3.2.2 基于类的动态代理的代码示例

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

// 1. 定义目标类
class RealSubject {
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

// 2. 实现MethodInterceptor接口
class CglibProxyInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("CglibProxy: Before handling request.");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("CglibProxy: After handling request.");
        return result;
    }
}

// 3. 生成代理对象
public class CglibProxyDemo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new CglibProxyInterceptor());
        RealSubject proxySubject = (RealSubject) enhancer.create();
        proxySubject.request();
    }
}

3.2.3 基于类的动态代理的优缺点

优点: - 可以代理没有实现接口的类。 - 灵活性高,可以在运行时动态生成代理对象。

缺点: - 需要引入第三方库(如CGLIB),增加了项目的复杂性。 - 代理对象的生成和调用过程较为复杂,性能开销较大。

4. 代理模式的应用场景

代理模式在实际开发中有广泛的应用,以下是一些常见的应用场景:

5. 总结

代理模式是Java中一种常用的设计模式,它通过创建一个代理对象来控制对原始对象的访问。代理模式可以分为静态代理和动态代理两种类型。静态代理在编译时就已经确定代理类和目标类的关系,而动态代理在运行时动态生成代理对象。代理模式在实际开发中有广泛的应用,例如远程代理、虚拟代理、保护代理和智能引用等。通过合理使用代理模式,可以提高代码的灵活性和可维护性。

推荐阅读:
  1. java中的代理模式是什么
  2. Java的代理模式有哪些

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:flex布局属不属于css3的

下一篇:Vue中使用axios调用后端接口的坑怎么解决

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》