Aop编程之动态代理

news2024/11/17 11:28:50

1、Java代理介绍

Java中的代理方式包括静态代理和动态代理。 静态代理在编译期间就确定了代理对象,动态代理是在运行期间动态生成代理对象。动态代理包括cglib动态代理和jdk动态代理,在目标对象有接口的情况下,可以使用jdk动态代理或者cglib动态代理;如果目标对象没有接口,则无法使用jdk动态代理,只能使用cglib动态代理。下面是介绍分别实现cglib动态代理和jdk动态代理的简单例子。

2、cglib动态代理

下面的例子中, 要增强User类的talk()方法,在方法开始和结束时都输出当前的系统时间,但是不希望修改User类的代码,又因为User类没有实现接口,在这种情况下可以使用cglib动态代理实现。

代码逻辑:

  1. 创建User类,并且编写talk()方法;
  2. 创建User类的代理增强类,用于增强talk()方法的代码逻辑;
  3. 编写测试类,先创建一个User对象,然后通过增强类根据这个对象创建一个增强对象,最后执行增强对象的talk方法。

  • User类
public class User {
    public void talk(){
        System.out.println("【交谈中。。。】");
    }
}

  • User代理增强类
  1. 执行Enhancer.create()方法,传入对应的参数,拿到一个增强后的对象;
  2. 重写MethodInterceptor()接口的 intercept()方法 编写具体的增强代码逻辑。
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class UserExtendByCglib {
    public static Object getProxy(Object target){
        /**
         * Enhancer.create()方法, 参数1是对象的字节码, 参数2是拦截方法的程序的对象, 返回值是一个增强后的对象
         */
        return Enhancer.create(target.getClass(), new MethodInterceptor() {
            /**
             * @param proxy  增强后的代理对象
             * @param method  需要代理增强的方法
             * @param args     需要代理增强的方法的参数
             * @param methodProxy  增强后的代理对象的方法
             */
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                //增强代码逻辑1:开始时间
                System.out.println(System.currentTimeMillis());
                //执行最初的方法
                Object result = method.invoke(target, args);
                //增强代码逻辑2:结束时间
                System.out.println(System.currentTimeMillis());
                return result;
            }
        });
    }
}

  • 测试代码
public class TestUser {
    public static void main(String[] args) {
        // 创建未被增强的对象
        User user = new User();
        // 通过代理对象, 对初始对象增强, 然后得到一个增强对象
        User userProxy = (User) UserExtendByCglib.getProxy(user);
        // 执行增强后的方法
        userProxy.talk();

    }
}

3、jdk动态代理

在下面的例子中,想要对Student类的talk方法增强,talk是Student实现Talk接口重写后的方法,这种情况可以使用jdk动态代理实现。

代码逻辑:

  1. 定义一个Talk接口,其中包含talk()方法;
  2. 创建Student类,实现Talk接口,重写talk()方法;
  3. 创建Talk接口的代理增强类,用于增强talk()方法的代码逻辑;
  4. 编写测试类,先创建一个Student对象,然后通过增强类根据这个对象创建一个增强对象,最后执行增强对象的talk()方法。
  • 创建talk接口
public interface Talk {
    void talk();
}

  • 创建talk接口的实现类
public class Student implements Talk{
    @Override
    public void talk() {
        System.out.println("【交谈中。。。】");
    }
}

  • 创建talk接口的增强代理类
  1. 通过执行Proxy.newProxyInstance()方法拿到一个代理对象;
  2. 重写接口InvocationHandler的invoke()方法编写具体的增强逻辑。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TalkProxyByJdk {

    public static Object getProxy(Object target){
        Object proxy = Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * @param proxy  增强后的代理对象
                     * @param method 需要代理增强的方法
                     * @param args   需要代理增强的方法的参数
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开始说话的时间:"+System.currentTimeMillis());
                        Object result = method.invoke(target, args);
                        System.out.println("停止说话的时间:"+System.currentTimeMillis());
                        return result;
                    }
                }
        );
        return proxy;
    }

}

  • 测试代理对象
import java.lang.reflect.Proxy;
public class TestJdkProxy {
   public static void main(String[] args) {
       // 创建初始对象 
        Talk student = new Student();
       // 创建代理对象 
        Talk proxy = (Talk) TalkProxyByJdk2.getProxy(student);
       // 执行代理对象的增强方法 
        proxy.talk();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1371995.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyTorch项目源码学习(2)——Tensor代码结构初步学习

PyTorch版本:1.10.0 Tensor Tensor是Pytorch项目较为重要的一部分,其中的主要功能如存储,运算由C和CUDA实现,本文主要从前端开始探索学习Tensor的代码结构。 结构探索 PyTorch前端位于torch目录下,从_tensor.py可以…

手持终端PDA定制厂家_5G安卓手持机设备/条形码扫描手持机PDA

手持终端PDA是一种功能强大的手持终端设备,具备一维码和二维码扫描功能,广泛应用于门票管理、零售、智能巡检、仓储物资管理、金融、快递等领域。 这款手持终端基于MT6877方案,搭载八核处理器(2xCortex-A78 2.4GHz 6xCortex-A55 2.0GHz)&…

【机器学习前置知识】狄利克雷分布

在阅读本文前,建议先食用以下几篇文章以能更好地理解狄利克雷分布: 二项分布 Beta分布 多项分布 共轭分布 狄利克雷分布 狄利克雷分布(Dirichlet distribution)是Beta分布的扩展,把Beta分布从二元扩展到多元形式就是狄利克雷分布&#…

【PixPin】比Snipaste、QQ的截图长图和动图还好用的截图工具

1.下载地址—— 下载地址 2.下载压缩包 双击exe文件运行 按默认的来 中文安装 选择安装路径 下一步,安装 安装完成,可以自己设置快捷键

使用Django框架自带的Form表单完成简单的用户登录注册

如果不知道怎么配置Django环境以及如何连接数据库请点击我的上一篇博客: 使用pycharm初始化Django框架并连接Sql Server 文章目录 1.Django默认生成的数据表2.用户登录2.1创建登录页面2.2视图处理登录请求2.3配置访问路径 3.用户注册3.1创建用户表单3.2创建注册模版…

VScode代码格式化

Vscode代码格式化 有时候总是想,为什么我的代码格式化完后为什么这么挤,而且不想让代码在格式化后换行,他总是自动换行,所以我去网上查了相关资料 第一步,搜索插件ESLint并安装,安装完成后你就可以进行格式化了 第二步,设置中选择settings,搜索Tab size,根据一下图片更改 第…

全志T113开发板Qt远程调试

1引言 通常情况下工程师在调试Qt程序时,需要频繁制作镜像烧录到核心板来测试Qt程序是否完善,这样的操作既费时又费力。这时我们可以通过QtCreator设备功能,定义设备后,在x86_64虚拟机上交叉编译qt程序,将程序远程部署到…

ubuntu 18.04网络问题

ubuntu 18.04网络问题汇总 准备工作一、有线网卡不可用二、无法访问外网 准备工作 安装好系统之后,检查gcc和make是否已经安装 $ which gcc /usr/bin/gcc $ which make /usr/bin/make如果未安装,则安装gcc和make $ apt install gcc $ apt install mak…

Golang协程池ants库的学习、使用及源码阅读,协程池与GMP模型关系的理解

前言 在工作时遇到了一个需要使用ants协程池的地方,因此顺带来学习一下他的原理。 协程池 Golang的资源还是偏少一些…因此先简单的参考学习了一下线程池。 类似于Java中的线程池,协程池也是为了减少协程频繁创建、销毁所带来资源消耗的问题。按默认每…

【我想开发一个小程序,大概需要多少钱?】

小程序开发为什么报价差距很大?主要是因为小程序的实现方法和功能模型不同。 小程序的实现方法: 实现方法主要分为SAAS小程序、定制小程序和第三方平台小程序。不同的实现方法价格都是不一样的,大概的区间如下: SAAS小程序和第三…

ChatGPT+Python近红外光谱数据分析及机器学习与深度学习建模进阶应用

目录 第一章 ChatGPT4入门基础 第二章 ChatGPT4 提示词使用方法与技巧 第三章 ChatGPT4助力信息检索与总结分析 第四章 ChatGPT4助力论文写作与投稿 第五章 ChatGPT4助力Python入门基础 第六章 ChatGPT4助力近红外光谱数据预处理 第七章 ChatGPT4助力多元线性回归近红外…

leetcode经典【双指针】例题

删除有序数组中的重复项: https://leetcode.cn/problems/remove-duplicates-from-sorted-array/ 解题思路: 首先注意数组是有序的,那么重复的元素一定会相邻。 注: 要求删除重复元素,实际上就是将不重复的元素移到数组的左侧。 考…

ubuntu20.04安装cuda11.4以及cudnn

系统:ubuntu20.04硬件配置:GPU3080、CPU未知通过《软件和更新》在附加驱动选项中添加了驱动: 1.检查自己电脑支持的cuda nvidia-smi4. 下载cuda11.4.2 wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/c…

典型的无人机打击技术

无人机打击技术主要指的是用于中和、摧毁或干扰无人机(UAV)的各种技术手段。 这些技术随着无人机的广泛使用而迅速发展,特别是在军事和安全领域。下面是一些主要的无人机打击技术及其原理: 射频干扰(RF Jamming&#x…

算法通关村番外篇-LeetCode编程从0到1系列六

大家好我是苏麟 , 今天带来LeetCode编程从0到1系列六 . 链表相关的题目 , 也是面试热题 . 大纲 21. 合并两个有序链表206. 反转链表 21. 合并两个有序链表 描述 : 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 题目 : Le…

苹果手机设置静态IP教程,长效IP代理有什么帮助?

随着智能手机的普及,越来越多的人开始使用苹果手机。然而,有时候我们在使用苹果手机时,可能会遇到需要设置静态IP的情况。那么,如何在苹果手机上设置静态IP呢?下面就为大家详细介绍一下。 1、打开苹果手机,…

LINUX基础第十一章:文件系统与日志服务管理

目录 一.LINUX文件系统 1.inode表和block (1)inode (2)block 2.查看inode号命令 3.Linux系统文件三种主要时间属性 4.磁盘空间还剩余很多但无法继续创建文件 5.inode大小 二.日志 1.日志保存位置 2.日志文件的分类 &am…

关于java的稀疏数组

关于java的稀疏数组 我们在前面的文章中了解了冒泡排序和优化冒泡排序,在本篇文章中我们来介绍一下稀疏数组,我们学会了可以自己动手试一试😀 稀疏数组 在介绍稀疏数组之前,我们先来了解一下五子棋。 我们这里有一个11 x 11的棋…

新手练习项目 4:简易2048游戏的实现(C++)

名人说:莫听穿林打叶声,何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder) 目录 一、效果图二、代码(带注释)三、说明 一、效果图 二、代码(带…

深度学习|交叉熵

文章目录 什么是交叉熵如何构造信息量的函数关于 C 1 C_1 C1​参数的选择关于 C 2 C_2 C2​参数的选择 一个系统的熵如何比较两个系统的熵交叉熵在神经网络中的应用参考 什么是交叉熵 熵是用来衡量一个系统的混乱程度,混乱程度也其实代表着整个系统内部的不确定性。…