带你重新认识Java动态代理

带你重新认识Java动态代理

什么是动态代理?

代理模式是一种设计模式,它允许我们创建一个对象,该对象充当其他对象的代表或占位符,以便控制对这些对象的访问。

在Java中,我们可以使用静态代理和动态代理。其中,静态代理需要自行编写代理类,因此显得比较复杂。而动态代理则可以通过Java API来实现,大大减少了编程的工作量。

动态代理是Java中的一项高级编程技术,它允许我们在运行时动态生成代码,从而实现代理对象的创建和管理。在动态代理模式中,我们不需要显式地编写代理类,而是依赖于Java反射机制在运行时生成代理对象并自动处理代理方法。

动态代理的优点

  • 类的职责分离:代理类作为原有类的代理,可以将一些原有类中的方法抽象出来,保留真正关心的核心业务逻辑,使得代理类具有更高的聚合性和可维护性。
  • 代码复用:一个代理类可以代理多个委托类,而静态代理则需要每个委托类对应一个代理类,代码冗余度更高。
  • 高可扩展性:动态代理在实现时使用反射机制,在运行时动态地创建了代理类的对象,因此可以在代理类的实现上进行更多的扩展,实现更复杂的业务逻辑。

动态代理的缺点

  • 性能较差:由于动态代理的实现机制是基于反射实现的,因此在运行时会有额外的开销,而静态代理则可以直接调用委托对象的方法,效率更高。
  • 编程复杂度高:相较于静态代理,动态代理实现的过程较为复杂,需要涉及到反射机制、方法调用等多个方面。

举例说明

下面我们通过两个示例来详细说明动态代理的实现过程。

示例1

首先,我们需要定义一个接口UserService,并在其中定义一个getUser方法。

public interface UserService {
    User getUser(String name);
}

然后,我们定义一个UserServiceImpl类来实现接口中的方法。

public class UserServiceImpl implements UserService {
    @Override
    public User getUser(String name) {
        return new User(name);
    }
}

其中,User类是一个简单的JavaBean类,用来存储用户信息。

public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

接着,我们定义一个UserInvocationHandler类,用来处理代理对象的方法调用。

public class UserInvocationHandler implements InvocationHandler {
    private UserService userService;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before invoke method: " + method.getName());
        Object result = method.invoke(userService, args);
        System.out.println("after invoke method: " + method.getName());
        return result;
    }
}

最后,我们在main方法中创建一个代理对象,并调用其getUser方法。在代理对象调用getUser方法之前和之后,都会输出一些调试信息。

public static void main(String[] args) {
    UserService userService = new UserServiceImpl();
    UserInvocationHandler invocationHandler = new UserInvocationHandler(userService);
    UserService proxy = (UserService) Proxy.newProxyInstance(
            UserService.class.getClassLoader(),
            new Class[]{UserService.class},
            invocationHandler);
    User user = proxy.getUser("Tom");
    System.out.println("get user: " + user.getName());
}

示例2

接下来,我们用另外一个示例来说明动态代理的实现过程。

首先,我们需要定义一个接口Calculator,并在其中定义两个方法addsubtract

public interface Calculator {
    int add(int x, int y);

    int subtract(int x, int y);
}

然后,我们定义一个CalculatorImpl类来实现接口中的方法。

public class CalculatorImpl implements Calculator {
    @Override
    public int add(int x, int y) {
        System.out.println("add: " + x + " + " + y);
        return x + y;
    }

    @Override
    public int subtract(int x, int y) {
        System.out.println("subtract: " + x + " - " + y);
        return x - y;
    }
}

接着,我们定义一个CalculatorInvocationHandler类,用来处理代理对象的方法调用。

public class CalculatorInvocationHandler implements InvocationHandler {
    private Calculator calculator;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before invoke method: " + method.getName());
        Object result = method.invoke(calculator, args);
        System.out.println("after invoke method: " + method.getName());
        return result;
    }
}

最后,我们在main方法中创建一个代理对象,并调用其addsubtract方法。在代理对象调用addsubtract方法之前和之后,都会输出一些调试信息。

public static void main(String[] args) {
    Calculator calculator = new CalculatorImpl();
    CalculatorInvocationHandler invocationHandler = new CalculatorInvocationHandler(calculator);
    Calculator proxy = (Calculator) Proxy.newProxyInstance(
            Calculator.class.getClassLoader(),
            new Class[]{Calculator.class},
            invocationHandler);
    int result1 = proxy.add(2, 3);
    System.out.println("result1: " + result1);
    int result2 = proxy.subtract(5, 2);
    System.out.println("result2: " + result2);
}

注意,在示例中,我们使用了Java反射机制来调用代理对象的方法。由于反射机制会带来额外的性能开销,因此在实际应用中需要慎重选择。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:带你重新认识Java动态代理 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • win10开机后键盘失灵重启才能使用如何解决 键盘重启后可用的解决方法

    Win10开机后键盘失灵重启才能使用如何解决 如果你在使用Windows 10时发现开机后键盘失灵,重启电脑才能使用,那么这篇文章就是为你准备的。我们将为您提供解决此问题的一些方法。 方法1:修复键盘驱动程序 键盘驱动程序可能在某些情况下被损坏,导致键盘失灵。在这种情况下,你需要尝试修复键盘驱动程序,以恢复键盘的正常工作。 在计算机管理器中打开设备管理器。 …

    other 2023年6月27日
    00
  • Android自定义ViewGroup实现选择面板

    下面是详细讲解 “Android自定义ViewGroup实现选择面板” 的完整攻略。 1. 前言 在日常的 App 开发中,我们经常会对页面进行布局的调整,比如添加选择面板。而这时,我们往往无法使用 Android 原生提供的布局组件来实现,因为我们需要的是一个自定义的布局组件,来实现我们自己的需求。 因此,通过本文,你将能够学习到如何自定义一个针对特定功能…

    other 2023年6月25日
    00
  • java 中序列化NotSerializableException问题解决办法

    当在 Java 中对一个对象进行序列化时,如果该对象的类没有实现 Serializable 接口,就会抛出 NotSerializableException 异常。解决这个问题的方法有两种: 方法一:实现 Serializable 接口 最直接的解决办法就是让该对象所属的类实现 Serializable 接口。Serializable 接口是一个标记接口,仅…

    other 2023年6月27日
    00
  • ppt中怎么设计立体浮雕字体效果?

    设计立体浮雕字体效果的完整攻略如下: 步骤一:选择适合的字体 在设计浮雕字体时,需要先选择适合的字体。建议选择粗体或黑体字体,这样在浮雕效果中更加突出。 示例一:选择粗体字体,例如 Arial Black。 步骤二:添加字体 在选定的文本框中输入需要设计浮雕效果的文字,可以直接在 PowerPoint 中自带的字体库中选择符合要求的字体。 示例二:在文本框中…

    other 2023年6月27日
    00
  • Android应用中使用Fragment组件的一些问题及解决方案总结

    Android应用中使用Fragment组件的一些问题及解决方案总结 Background Fragment是Android中的一个组件,与Activity类似,可以用于UI交互和视图管理。常见的使用场景是在大屏幕设备上,如平板电脑,可以将不同的功能区域以Fragment的形式分离开来,每个Fragment可以独立管理自己的生命周期和UI控件。 在实际的开发…

    other 2023年6月27日
    00
  • PHP准确取得服务器IP地址的方法

    PHP准确取得服务器IP地址的方法 在PHP中,有几种方法可以准确地获取服务器的IP地址。下面将介绍两种常用的方法。 方法一:使用$_SERVER全局变量 PHP的$_SERVER全局变量包含了与服务器相关的信息,其中包括服务器的IP地址。可以通过访问$_SERVER[‘SERVER_ADDR’]来获取服务器的IP地址。 示例代码: $serverIP = …

    other 2023年7月30日
    00
  • java性能监控工具:jmap命令详解

    Java性能监控工具:jmap命令详解 在Java应用程序开发中,性能监控一直是一个非常关键的问题。提高应用程序性能,不仅能够提升用户的体验,同时也能降低运维成本。而在性能监控过程中,jmap命令是一个非常强大的工具。 什么是jmap命令 jmap命令是一款Java虚拟机性能监控工具,能够打印出JVM中所有对象的信息。它可以用于定位内存泄漏、检查内存使用情况…

    其他 2023年3月29日
    00
  • JSON 数字排序多字段排序介绍

    JSON 数字排序多字段排序介绍 简介 JSON是一种基于键值对的轻量级数据交换格式,常用于前后端数据传输。在实际应用中,我们经常需要对JSON数据进行排序,例如对用户信息按照年龄和姓名进行排序,这时就需要使用多字段排序。 数字排序 升序和降序 对于仅包含数字的JSON数据,我们可以使用JavaScript内置的sort()方法进行排序。sort()的默认顺…

    other 2023年6月25日
    00
合作推广
合作推广
分享本页
返回顶部