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

动态代理

时间:2022-12-31 23:22:52浏览次数:50  
标签:Object 代理 接口 InvocationHandler 动态 public

动态代理

1. 什么是代理模式

代理模式是一种设计模式,就是通过代理对象操作原对象并且给原对象添加一些额外功能。

代理模式分为静态代理和动态代理两种

2. 静态代理

静态代理中,我们对目标对象的每个方法的增强都是手动完成的(*后面会具体演示代码*),非常不灵活(*比如接口一旦新增加方法,目标对象和代理对象都要进行修改*)且麻烦(*需要对每个目标类都单独写一个代理类*)。 实际应用场景非常非常少,日常开发几乎看不到使用静态代理的场景。

上面我们是从实现和应用角度来说的静态代理,从 JVM 层面来说, 静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。

----- 著作权归Guide哥所有。 链接: https://javaguide.cn/java/basis/proxy/#_1-代理模式

3. 动态代理

动态代理无序在编码阶段为每一个带代理类编码代理类,通过字节码技术等,在运行时动态生成代理对象。

常见的动态代理技术有:

  • jdk动态代理
  • cglib动态代理

3.1 jdk动态代理

Proxy的newProxyInstance(ClassLoader classloader,Class<?>[] interfaces,InvocationHandler handler);

这个方法一共有 3 个参数:

  1. loader :类加载器,用于加载代理对象。
  2. interfaces : 被代理类实现的一些接口;
  3. h : 实现了 InvocationHandler 接口的对象;

InvocationHandler类

public interface InvocationHandler {

    /**
     * 当你使用代理对象调用方法的时候实际会调用到这个方法
     */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

使用步骤:

  1. 定义一个接口及其实现类;
  2. 自定义 InvocationHandler 并重写invoke方法,在 invoke 方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑;
  3. 通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法创建代理对象;

代码示例:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface SendMessage{
    void send();
}
class MyProxy implements  SendMessage{

    @Override
    public void send() {
        System.out.println ("发送短信");
    }
}
class MyInvocationHandler implements InvocationHandler{
    private Object object;
    public MyInvocationHandler(Object o){
        this.object = o;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println ("执行之前统计");
        Object re = method.invoke (object,args);
        System.out.println ("执行之后统计");
        return re;
    }
}
public class ProxyExample {
    public static void main(String[] args) {
        MyProxy p = new MyProxy ();
        InvocationHandler handler = new MyInvocationHandler (p);
        SendMessage o = (SendMessage) Proxy.newProxyInstance (p.getClass ().getClassLoader (), p.getClass ().getInterfaces (), handler);
        o.send ();
    }
}

3.2 cglib动态代理

3.3 jdk 和 cglib的对比

JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。

就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。

----- 著作权归Guide哥所有。 链接: https://javaguide.cn/java/basis/proxy/#_3-2-cglib-动态代理机制

标签:Object,代理,接口,InvocationHandler,动态,public
From: https://www.cnblogs.com/zhf520/p/17017553.html

相关文章

  • [leetcode]第 10 天 动态规划(中等)
    46.把数字翻译成字符串思路每个数字都有两种翻译情况,一种是和前一位数字一起被翻译,一种是单独被翻译。状态定义:dp[i]表示以xi结尾的数字的翻译方案数量;状态转移方程:f......
  • Nginx 代理webSocket时60s自动断开, 保持长连接
    利用nginx代理websocket的时候,发现客户端和服务器握手成功后,如果在60s时间内没有数据交互,连接就会自动断开,如下图:为了保持长连接,可以采取来两种方式.1.nginx.conf文件里locati......
  • Nginx 代理websocket连接上限
    一.结论 1.nginx最多只能维持(65535*后端服务器IP个数)条websocket的长连接,如果后端websocket服务器IP只有一个,那么就只能最多支持65535条连接。瓶颈就产生在了nginx上......
  • 在Ubuntu上安装Azure DevOps代理程序
    Contents1概述2.安装Ubuntu18.04操作系统3.安装AzureDevOpsServer代理3.1安装AzureDevOpsServer代理3.2以服务方式运行代理1.概述Ubuntu是一个以桌面应用为主......
  • [leetcode]第 9 天 动态规划(中等)
    42.连续子数组的最大和思路状态定义:dp[i]表示以nums[i]结尾的连续子数组的最大和;状态转移方程:dp[i-1]>0,dp[i]=dp[i-1]+nums[i];dp[i-1]<=0,dp[i]=num......
  • SpringBoot动态更新yml文件
    前言在系统运行过程中,可能由于一些配置项的简单变动需要重新打包启停项目,这对于在运行中的项目会造成数据丢失,客户操作无响应等情况发生,针对这类情况对开发框架进行升级提......
  • Allure08-动态用例优先级与链接
    动态用例优先级allure.dynamic.severity(用例优先级)可以使用参数化的参数只能放到函数和方法中对于一个子功能或测试需求的每一条用例,都可以有自己的severity写法......
  • Allure06-动态测试集与功能特性
    动态测试集特性allure.dynamic.suite('某用例所属的测试集名称')动态特性放到函数或方法中不建议使用allure.dynamic.suite,否则会导致测试集名称显示混乱:既包含模块名......
  • Allure07-动态用例标题、用例描述和测试步骤
    动态用例标题allure.dynamic.title('动态用例标题')必须放在函数、方法之内可以使用参数化的参数每条用例执行一次会覆盖@allure.title动态用例描述allure.dy......
  • SpringBoot动态更新yml文件
    前言在系统运行过程中,可能由于一些配置项的简单变动需要重新打包启停项目,这对于在运行中的项目会造成数据丢失,客户操作无响应等情况发生,针对这类情况对开发框架进行升级提......