• Java代理简介


    代理简介

    Java中的代理是一种设计模式,它允许一个对象(代理对象)代表另一个对象(真实对象)来控制对真实对象的访问。代理对象通常拥有与真实对象相同的接口,这使得客户端可以通过代理来访问真实对象,而不需要知道或直接与真实对象交互。代理模式有多种用途,包括远程代理、虚拟代理、保护代理等。

    在Java中,代理可以通过以下两种方式实现:

    1. 静态代理:在编译时就已经确定代理关系,代理类需要手动编写。通常使用接口来定义代理类和真实类的共同接口,然后实现代理类和真实类,代理类中调用真实类的方法,并在调用前后可以添加额外的逻辑。

    2. 动态代理:在运行时动态生成代理类,无需手动编写代理类。Java提供了java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来支持动态代理。这种方式更灵活,适用于代理多个不同类型的对象。

    下面详细介绍动态代理的使用和应用:

    使用步骤

    1. 定义接口:首先,您需要定义一个接口,该接口将被代理类和代理对象实现。这个接口定义了真实对象和代理对象的方法。

    2. 创建真实对象:实现接口的真实对象,它是您要代理的对象。

    3. 实现InvocationHandler接口:创建一个实现java.lang.reflect.InvocationHandler接口的类,它将用于处理代理对象的方法调用。在invoke方法中,您可以在调用真实对象方法前后执行额外的逻辑。

    4. 创建代理对象:使用java.lang.reflect.Proxy类的newProxyInstance方法来创建代理对象。您需要提供类加载器、实现的接口数组和InvocationHandler的实例。

    5. 使用代理对象:现在,您可以使用代理对象来调用方法,它会在调用前后执行您定义的逻辑。

    示例

    假设我们有一个简单的接口UserService,它有一个方法getUser

    public interface UserService {
        User getUser(int userId);
    }
    
    public class User {
        private int userId;
        private String username;
    
        // Getters and setters
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    我们可以创建一个动态代理,记录方法调用的时间,并在真正调用之前打印日志:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class UserServiceProxy implements InvocationHandler {
        private UserService realUserService;
    
        public UserServiceProxy(UserService realUserService) {
            this.realUserService = realUserService;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 在方法调用前记录时间
            long startTime = System.currentTimeMillis();
            
            // 调用真正的方法
            Object result = method.invoke(realUserService, args);
            
            // 在方法调用后记录时间并打印日志
            long endTime = System.currentTimeMillis();
            System.out.println("Method " + method.getName() + " took " + (endTime - startTime) + " milliseconds.");
            
            return result;
        }
    
        public static void main(String[] args) {
            // 创建真实对象
            UserService realUserService = new RealUserService();
    
            // 创建代理对象
            UserService proxy = (UserService) Proxy.newProxyInstance(
                UserService.class.getClassLoader(),
                new Class[]{UserService.class},
                new UserServiceProxy(realUserService)
            );
    
            // 使用代理对象
            User user = proxy.getUser(123);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    这个示例中,UserServiceProxy实现了InvocationHandler接口,并在invoke方法中添加了日志记录。然后,我们通过Proxy.newProxyInstance方法创建了代理对象,并在调用getUser方法时记录了方法执行时间。

    应用场景

    1. 远程代理:允许客户端访问远程服务器上的对象,如远程方法调用(RMI)。
    2. 虚拟代理:用于延迟加载对象,例如在加载大型图像或复杂对象时。
    3. 保护代理:控制对对象的访问,以确保只有特定权限的客户端可以访问它。
    4. AOP(面向切面编程):使用代理来实现横切关注点,例如日志记录、事务管理等。
    5. 动态代理框架:许多Java框架和库,如Spring,使用动态代理来实现各种功能,如事务管理、依赖注入等。

    代理模式是一种强大的设计模式,可以提高代码的灵活性、可维护性和可扩展性,尤其是在需要添加额外逻辑或控制对对象的访问时非常有用。

  • 相关阅读:
    Linux基础-LVM逻辑卷管理
    redux原理分享
    【刷题笔记8】LeetCode 48. 旋转图像(数组模拟)
    大疆笔试题
    透明度模糊Android实现
    同步`AAA`数据库下的`purse`表到`BBB`数据库下的同名表
    怎么样可以算一名云原生工程师?
    【业务功能篇103】微服务下全局唯一分布式id生成器
    NIO之Selector执行流程
    Spring-boot初级
  • 原文地址:https://blog.csdn.net/Go_ahead_forever/article/details/133690076