侧边栏壁纸
博主头像
拾荒的小海螺博主等级

只有想不到的,没有做不到的

  • 累计撰写 192 篇文章
  • 累计创建 18 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

JAVA:代理模式(Proxy Pattern)的技术指南

拾荒的小海螺
2024-12-20 / 0 评论 / 0 点赞 / 7 阅读 / 6593 字

1、简述

代理模式(Proxy Pattern)是一种结构型设计模式,用于为其他对象提供一种代理,以控制对这个对象的访问。通过代理模式,我们可以在不修改目标对象代码的情况下扩展功能,满足特定的需求。

设计模式样例:https://gitee.com/lhdxhl/design-pattern-example.git

image-clsl.png


2、什么是代理模式?

代理模式的核心思想是通过一个代理对象来间接访问目标对象,从而为目标对象增加额外的功能或限制。代理模式的常见用途包括:

  • 控制访问:限制对目标对象的直接访问。
  • 延迟加载:当对象的创建成本较高时,通过代理模式实现按需加载。
  • 增强功能:在目标对象的行为前后添加其他逻辑。

代理模式通常由以下几个角色组成:

  • 抽象主题(Subject):定义目标对象和代理对象的共同接口。
  • 真实主题(RealSubject):实现了抽象主题的真实对象。
  • 代理(Proxy):持有对真实主题的引用,并通过实现抽象主题接口来控制对真实主题的访问。

3、实际案例

3.1 实现静态代理

一个 UserService 提供用户的基本操作,我们通过代理实现日志记录功能。

// 接口定义
public interface UserService {
    void addUser(String name);
}

// 目标类
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String name) {
        System.out.println("User added: " + name);
    }
}

// 代理类
public class UserServiceProxy implements UserService {
    private final UserService userService;

    public UserServiceProxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void addUser(String name) {
        System.out.println("[LOG] Adding user...");
        userService.addUser(name);
        System.out.println("[LOG] User added.");
    }
}

// 测试代码
public class StaticProxyDemo {
    public static void main(String[] args) {
        UserService userService = new UserServiceProxy(new UserServiceImpl());
        userService.addUser("Alice");
    }
}

输出:

[LOG] Adding user...
User added: Alice
[LOG] User added.

3.2 实现动态代理(JDK)

使用动态代理实现相同的日志功能。

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

// 动态代理类
public class UserServiceDynamicProxy implements InvocationHandler {
    private final Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("[LOG] Method " + method.getName() + " is called");
        Object result = method.invoke(target, args);
        System.out.println("[LOG] Method " + method.getName() + " execution completed");
        return result;
    }

    public static Object createProxy(Object target) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new UserServiceDynamicProxy(target)
        );
    }
}

// 测试代码
public class DynamicProxyDemo {
    public static void main(String[] args) {
        UserService userService = (UserService) UserServiceDynamicProxy.createProxy(new UserServiceImpl());
        userService.addUser("Bob");
    }
}

输出:

[LOG] Method addUser is called
User added: Bob
[LOG] Method addUser execution completed

3.3 实现动态代理(CGLIB)

使用 CGLIB 动态代理实现日志功能(适用于没有实现接口的类)。

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

// 目标类
public class ProductService {
    public void addProduct(String product) {
        System.out.println("Product added: " + product);
    }
}

// CGLIB 代理类
public class ProductServiceCglibProxy implements MethodInterceptor {
    private final Object target;

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

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("[LOG] Method " + method.getName() + " is called");
        Object result = method.invoke(target, args);
        System.out.println("[LOG] Method " + method.getName() + " execution completed");
        return result;
    }

    public static Object createProxy(Object target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new ProductServiceCglibProxy(target));
        return enhancer.create();
    }
}

// 测试代码
public class CglibProxyDemo {
    public static void main(String[] args) {
        ProductService productService = (ProductService) ProductServiceCglibProxy.createProxy(new ProductService());
        productService.addProduct("Laptop");
    }
}

输出:

[LOG] Method addProduct is called
Product added: Laptop
[LOG] Method addProduct execution completed

4、应用场景

  • 权限控制:例如,在 Spring 中使用 AOP 动态代理来实现权限校验。
  • 事务管理:在数据库操作前后添加事务逻辑。
  • 远程方法调用:例如 RMI(远程方法调用)框架中代理的使用。
  • 缓存机制:在目标方法前后添加缓存逻辑。
  • 监控与日志:记录方法调用的频率、执行时间等。

5、总结

代理模式为我们提供了一种灵活的设计方案,既可以增强目标对象的功能,又能控制其访问。在实际开发中,根据需求选择静态代理还是动态代理可以更好地解决问题。同时,利用 JDK 和 CGLIB 动态代理的能力,可以让我们的代码更具扩展性和动态性。

0

评论区