首页 > 其他分享 >动态代理

动态代理

时间:2024-12-01 23:21:53浏览次数:11  
标签:target Object 代理 接口 HelloService 动态 public

动态代理有哪几种实现方式?

什么是动态代理?

动态代理是一种在运行时动态生成代理对象,并在代理对象上进行方法调用的编程技术。它主要用于在不修改原有代码基础上,增加或改变某些功能的执行流程。动态代理广泛应用于AOP(面向切面编程)、RPC(远程过程调用)、事务管理等领域。在Java中,主要有两种动态代理的实现方式:JDK动态代理和CGLIB动态代理。

JDK动态代理

定义:

JDK动态代理是基于接口的代理技术。它使用 java.lang.reflect.Proxy代理类和
java.lang.reflect.InvocationHandler接口来创建代理对象。当你调用代理对象的任何方法时,调用会被转发到InvocationHandler 的 invoke方法。你可以在这个invoke方法中定义拦截逻辑,比如前置处理、后置处理等。

你的类必须实现一个或多个接口,局限性只能代理接口方法

实现:
  • 定义一个接口及其实现类。

  • 创建一个实现了InvocationHandler接口的类,在该类的invoke方法中定义代理逻辑。

  • 通过[Proxy.nevProxyInstance](//通过 Proxy.newProxyInstance 方法动态创建接口的代理对象
    public static void main(String[] args) {
    // 创建目标对象
    HelloService target = new HelloServiceImpl();
    // 创建调用处理器对象
    HelloServiceHandler handler = new HelloServiceHandler(target);
    // 创建代理对象
    HelloService proxyInstance = (HelloService) Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    target.getClass().getInterfaces(),
    handler);

    ​ // 通过代理对象调用方法

    ​ proxyInstance.sayHello("World");

    }

    )方法动态创建接口的代理对象。

1.定义一个接口及其实现类

// 定义一个接口
public interface HelloService {
    void sayHello(String name);
}

// 实现该接口的类
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello, " + name);
    }
}

2.创建一个实现了InvocationHandler接口的类

//创建一个实现 InvocationHandler 接口的类
public class HelloServiceHandler implements InvocationHandler {
    //目标对象
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before sayHello");
        // 执行目标对象的方法
        Object result = method.invoke(target, args);
        System.out.println("After sayHello");
        return result;
    }
}

3.通过 Proxy.newProxyInstance 方法动态创建接口的代理对象

//通过 Proxy.newProxyInstance 方法动态创建接口的代理对象
public static void main(String[] args) {
    // 创建目标对象
    HelloService target = new HelloServiceImpl();
    // 创建调用处理器对象
    HelloServiceHandler handler = new HelloServiceHandler(target);
    // 创建代理对象
    HelloService proxyInstance = (HelloService) Proxy.newProxyInstance(
        target.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        handler);
    // 通过代理对象调用方法
    proxyInstance.sayHello("World");
}

Cglib动态代理

不需要接口,它是通过继承方式实现代理的

CGLIB底层通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不仅可以代理普通类的方法,还能代理那些没有接口的类的方法。

优点以及缺点:
  • 优点:无需接口实现。在大量调用的场景下,其生成的代理对象在调用时性能比JDK动态代理高
  • 缺点:对final方法无效,需添加额外的依赖。
实现:
  • 创建一个被代理的类
  • 创建一个继承MethodInterceptor的代理类,在intercept方法中定义代理逻辑
  • 使用Enhancer类创建被代理类的子类,并设置回调

1.创建一个被代理的类

//定义一个普通类
public class HelloService {
    public void sayHello(String name) {
        System.out.println("Hello, " + name);
    }
}

2.创建一个继承MethodInterceptor的代理类,在intercept方法中定义代理逻辑

//创建一个继承 MethodInterceptor 的代理类 实现 intercept 方法
public class HelloServiceCglib implements MethodInterceptor {
    private Object target;

    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        // 设置回调
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before sayHello");
        // 执行目标类的方法
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After sayHello");
        return result;
    }
}

3.实现

//实现
public static void main(String[] args) {
    HelloService target = new HelloService();
    HelloServiceCglib cglib = new HelloServiceCglib();
    HelloService proxy = (HelloService) cglib.getInstance(target);
    proxy.sayHello("World");
}

image-20241201231417370

标签:target,Object,代理,接口,HelloService,动态,public
From: https://www.cnblogs.com/wnbzw/p/18580613

相关文章

  • 渗透必修课:用Proxifier解锁代理的无限可能!
    概述在渗透测试的过程中,代理技术的应用贯穿始终。从前期的外部打点到后期的内网渗透,代理都是不可或缺的工具。在初期阶段,面对WAF的拦截,扫描器和渗透工具需要频繁更换IP以规避拦截;而在后期,通过工具如Frp和Nps出网后,代理可以帮助我们更好地进入目标内网开展进一步测试。1.Prox......
  • IDA+WSL2实现本地linux动态调试
    1、首先在ida安装目录找到dbgsrv这个文件夹,打开后把“linux_server”这个文件拖到你的linux中(我放在/root位置)2、然后赋予两个文件权限(linux-server和要调试的文件)chmod+x/root/linux_serverchmod+x你的待调试文件位置然后运行调试组件/root/linux_server64参数:“-p......
  • 【优选算法篇】一文读懂滑动窗口:动态调整范围的算法利器(上篇)
    文章目录须知......
  • 算法日记 36-38day 动态规划
    今天把动态规划结束掉,包括子序列以及编辑距离题目:最长公共子序列1143.最长公共子序列-力扣(LeetCode)给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。一个字符串的 子序列 是指这样一个新的字符串......
  • DConf —— 应用的动态配置
    我相信大多数开发者在编写应用程序时,都会面临一个基本问题:如何在应用启动时进行配置。我通常使用环境变量(ENVs)来设置一些可以根据运行环境或时间改变的值。然而,这些配置仅在应用启动时生效。如果我们需要更改配置,该怎么办呢?显然,我们需要用新的配置值重启应用。在某些情况下,这样做......
  • 动态顺序表
    顺序表(动态)顺序表分为静态和动态,静态的顺序表和动态顺序表相关接口的实现差别不大,因此不在赘述。头文件定义类型定义#pragmaonce#include<stdio.h>#include<stdlib.h>#include<assert.h>//#defineN10#defineINIT_CAPACITY4//给顺序表一个初始大小t......
  • Burp入门(2)-代理功能介绍
      声明:学习视频来自b站up主泷羽sec,如涉及侵权马上删除文章 感谢泷羽sec团队的教学视频地址:burp功能介绍(1)_哔哩哔哩_bilibili本文详细介绍burp的代理功能。一、插件配置代理1.安装代理插件(Google、Edge安装方式同Firefox一致,这里以Firefox为例)  打开扩展商店 :......
  • 反向代理模块
     1概念 1.1反向代理概念反向代理是指以代理服务器来接收客户端的请求,然后将请求转发给内部网络上的服务器,将从服务器上得到的结果返回给客户端,此时代理服务器对外表现为一个反向代理服务器。对于客户端来说,反向代理就相当于目标服务器,只需要将反向代理当作目标服务器......
  • vue基础之4:el与data的两种写法、理解MVVM、Object.defineProperty方法、数据代理
    欢迎来到“雪碧聊技术”CSDN博客!在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将不断探索Java的深邃世界,分享最新的技术动态、实战经验以及项目......
  • 使用css3绘制一个圆形动态的时钟
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>CSSClock</title>......