Java JDK动态代理(AOP)用法及实现原理详解

Java JDK动态代理(AOP)用法及实现原理详解

1. 什么是动态代理(AOP)?

动态代理是一种代理设计模式中的一种实现方式。一般的代理模式需要我们手动编写代理对象来实现代理,但是动态代理允许我们在运行时动态的创建代理对象,这样就无需手动编写代理对象了。常常使用动态代理实现切面编程(AOP)。

2. Java JDK动态代理实现原理

动态代理是基于Java反射机制实现的。Java JDK中提供了两个类:java.lang.reflect.InvocationHandler负责调用处理器的接口和java.lang.reflect.Proxy用来生成代理对象。 JDK动态代理的实现原理主要分成以下三个步骤:

  1. 创建InvocationHandler接口的实现类(调用处理器类),并实现invoke()方法,该方法是动态代理的核心,用于聚拢目标方法和增强代码,并返回结果。
  2. 获取类的ClassLoader和所有接口interfaces。
  3. 通过Proxy.newProxyInstance()方法创建代理实例。

3. Java JDK动态代理示例1

实现一个动态代理类,当调用目标方法时,打印方法名和参数,并在方法执行前后加上增强代码。

public interface UserService {
    void save(String name);
}

public class UserServiceImpl implements UserService {
    @Override
    public void save(String name) {
        System.out.println("save user: " + name);
    }
}

public class UserInvocationHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("准备执行 " + method.getName() + " 方法,参数为 " + Arrays.toString(args));
        Object result = method.invoke(target, args);
        System.out.println(method.getName() + " 方法执行完毕,返回结果: " + result);
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        InvocationHandler invocationHandler = new UserInvocationHandler(userService);
        UserService proxy = (UserService) Proxy.newProxyInstance(
                userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                invocationHandler);
        proxy.save("张三");
    }
}

4. Java JDK动态代理示例2

使用动态代理实现AOP,假设有一个学生类Student,它的某个方法study(),我们要在调用study()方法前后打印日志,示例代码如下:

public interface Student {
    void study(String course);
}

public class StudentImpl implements Student {
    @Override
    public void study(String course) {
        System.out.println("学生正在学习 " + course);
    }
}

public class StudentLog {
    public void beforeStudy() {
        System.out.println("准备学习,开始记录日志");
    }

    public void afterStudy() {
        System.out.println("学习完毕,结束记录日志");
    }
}

public class StudentInvocationHandler implements InvocationHandler {
    private Object target;
    private Object aspect;

    public StudentInvocationHandler(Object target, Object aspect) {
        this.target = target;
        this.aspect = aspect;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Method beforeMethod = aspect.getClass().getMethod("beforeStudy");
        Method afterMethod = aspect.getClass().getMethod("afterStudy");
        beforeMethod.invoke(aspect);
        Object result = method.invoke(target, args);
        afterMethod.invoke(aspect);
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Student student = new StudentImpl();
        StudentLog studentLog = new StudentLog();
        StudentInvocationHandler handler = new StudentInvocationHandler(student, studentLog);

        Student proxy = (Student) Proxy.newProxyInstance(
                student.getClass().getClassLoader(),
                student.getClass().getInterfaces(),
                handler);

        proxy.study("数学");
    }
}

5. 总结

以上,就是Java JDK动态代理(AOP)用法及实现原理详解的完整攻略。动态代理具有很强的灵活性和通用性,可以节约大量代码和维护代理对象的时间。使用动态代理方式进行AOP编程能够很好地解决大量重复代码和模板代码的问题,使得程序变得更加清晰和简洁。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java JDK动态代理(AOP)用法及实现原理详解 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • javassist使用指南

    Javassist使用指南 Javassist是一款Java字节码操作库,可用于在运行时动态地编辑、生成和转换Java字节码。它为Java字节码操作提供了一种简单而强大的API。 本篇教程将向您介绍Javassist的基本用法,包括如何创建和修改类,添加/删除字段和方法,并在代码中使用生成的类。 环境准备 在开始使用Javassist之前,需要确保您已完成以…

    Java 2023年5月26日
    00
  • springboot使用Logback把日志输出到控制台或输出到文件

    下面是使用Spring Boot集成Logback将日志输出到控制台或文件的完整攻略。 步骤1: 添加Logback和Spring Boot的依赖 首先需要在pom.xml文件中添加Logback和Spring Boot的依赖: <!– Logback for logging –> <dependency> <groupId…

    Java 2023年5月26日
    00
  • JAVA内存溢出解决方案图解

    JAVA内存溢出解决方案图解 什么是内存溢出 首先,了解内存溢出的概念非常重要。内存溢出指的是在运行Java程序时,程序需要使用的内存超出了JVM可提供的内存大小,导致程序崩溃的现象。 内存溢出通常发生在以下两种情况下: 应用程序如果需要的堆内存大小超过了JVM设置的最大堆内存空间。 应用程序中存在内存泄漏问题,导致内存被浪费而没有得到垃圾回收,最终导致内存…

    Java 2023年5月19日
    00
  • Apache2.2以上版本与Tomcat整合配置及负载均衡实现

    Apache2.2以上版本与Tomcat整合配置及负载均衡实现 前言 当我们想要将Tomcat应用服务器与Apache Web服务器整合在一起使用时,我们可以使用mod_jk这个Apache模块,它可以实现负载均衡和反向代理等功能。本文介绍了如何通过配置mod_jk实现Apache2.2以上版本与Tomcat的整合以及负载均衡实现。 准备工作 在开始整合之前…

    Java 2023年5月19日
    00
  • bat批处理一键登录网易163和126邮箱

    以下是“bat批处理一键登录网易163和126邮箱”的完整攻略。 1. 准备工作 首先,需要在自己电脑上安装好编辑器,比如notepad++,用来编辑和保存.bat文件。然后,需要了解一些基本的批处理语法。 2. 创建批处理文件 在notepad++中新建空白文本文件,然后在文件中输入以下内容: @echo off set /p user=请输入邮箱账号: …

    Java 2023年6月16日
    00
  • 阿里云发布 Spring Boot 新脚手架工程

    阿里云发布了Spring Boot新脚手架工程,使用脚手架可以快速创建Spring Boot项目,省去很多繁琐的配置工作,让开发人员能够迅速地开始项目开发。 步骤一:选择脚手架 首先,打开阿里云开发者中心官网,搜索“Spring Boot脚手架”,选择第一个来自官方的结果“Spring Boot 2.x 脚手架”,进入项目首页。 步骤二:创建工程 在页面上方…

    Java 2023年5月15日
    00
  • maven配置阿里云仓库的实现方法

    下面是关于”Maven配置阿里云仓库的实现方法”的完整攻略: 为什么需要配置阿里云仓库 Maven是一个可扩展的构建工具,它自带默认仓库地址,但是默认仓库的下载速度非常慢,因此我们可以使用其他仓库镜像来提高下载速度。阿里云提供了Maven的镜像仓库,使用阿里云仓库可大大提高Maven包的下载速度。 阿里云仓库配置方法 在maven/conf/settings…

    Java 2023年5月20日
    00
  • 简单总结Java IO中stream流的使用方法

    下面是“简单总结Java IO中stream流的使用方法”的完整攻略: 1. Java IO中的Stream流 Java IO(Input/Output)是指Java语言中的输入输出流操作,用于读取和写入数据。在Java IO中,输入输出是用Stream(流)的方式进行的。Stream流提供了InputSteam和OutputStream两个抽象类,它们是所…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部