Java动态代理分析

Java中的动态代理——附带动态代理源码跟踪分析 代理是基本的设计模式之一,它是为了插入一些额外操作或者不同操作而插入的“实际”对象的对象,它通常在实际被访问对象与访问者之间承当着中间人的职能,代替访问者去访问真实对象。当然有,接下来,我将采用动态代理的方式简化代理类的代码,让一个类实现N个代理类的功能。如果能看到生成的Proxy内部的实现,动态代理的谜团就解开了,继续跟踪Step6。在项目根目录下会生成一个文件夹,java动态代理生成的类都以$ProxyX命名,调试代码的时候看到这种命名的类,那么这个类就是动态代理生成的。代理类的内部长啥样? 阅读详情

Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地制定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分配到委托对象上反射执行,配置执行过程中,开发人员还可以进行修改

代理设计模式

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息、过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
1. 为了保持行为的一致性,代理类和委托类通常会实现相同的接口
2. 引入代理能够控制对委托对象的直接访问,可以很好的隐藏和保护委托对象,也更加具有灵活性

相关的类和接口

要了解 Java 动态代理的机制,首先需要了解以下相关的类或接口:
1. java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象
2. java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个invoke方法,用于几种处理在动态代理类对象上的方法调用。通常在该方法中实现对委托类的代理访问。
3. java.lang.ClassLoader:Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个.class 文件中。

代理机制及其特点

首先让我们来了解一下如何使用 Java 动态代理。具体有如下四步骤:
1. 通过实现 InvocationHandler 接口创建自己的调用处理器;
2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
// 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用
InvocationHandler handler = new InvocationHandlerImpl(..); 

// 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象
Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... }); 

// 通过反射从生成的类对象获得构造函数对象
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class }); 

// 通过构造函数对象创建动态代理类实例
Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });

实际使用过程更加简单,因为 Proxy 的静态方法 newProxyInstance 已经为我们封装了步骤 2 到步骤 4 的过程,所以简化后的过程如下

// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
InvocationHandler handler = new InvocationHandlerImpl(..); 

// 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader, 
     new Class[] { Interface.class }, 
     handler );

特点

动态生成的代理类本身的一些特点
1. 包:如果所代理的接口都是 public 的,那么它将被定义在顶层包(即包路径为空),如果所代理的接口中有非 public 的接口(因为接口不能被定义为 protect或private,所以除 public之外就是默认的package访问级别,那么它将被定义在该接口所在包,这样设计的目的是为了最大程度的保证动态代理类不会因为包管理的问题而无法被成功定义并访问;
2. 类修饰符:该代理类具有 final 和 public 修饰符,意味着它可以被所有的类访问,但是不能被再度继承;
3. 类名:格式是“$ProxyN”,其中 N 是一个逐一递增的阿拉伯数字,代表 Proxy 类第 N 次生成的动态代理类,值得注意的一点是,并不是每次调用 Proxy 的静态方法创建动态代理类都会使得 N 值增加,原因是如果对同一组接口(包括接口排列的顺序相同)试图重复创建动态代理类,它会很聪明地返回先前已经创建好的代理类的类对象,而不会再尝试去创建一个全新的代理类,这样可以节省不必要的代码重复生成,提高了代理类的创建效率。
4. 类继承关系:Proxy 类是它的父类,这个规则适用于所有由 Proxy 创建的动态代理类。而且该类还实现了其所代理的一组接口;
这里写图片描述
代理类实例的一些特点
1. 每个实例都会关联一个InvocationHandler(调用处理器对象),在代理类实例上调用其代理接口中声明的方法时,最终都会由InvocationHandler的invoke方法执行;
2. java.lang.Object中有三个方法也同样会被分派到调用处理器的 invoke 方法执行,它们是 hashCode,equals 和 toString;

被代理接口的一组特点
1. 要注意不能有重复的接口
2. 接口对于类装载器必须可见,否则类装载器将无法链接它们
3. 被代理的所有非 public 的接口必须在同一个包中,接口的数目不能超过65535

美中不足

Proxy只能对interface进行代理,无法实现对class的动态代理。观察动态生成的代理继承关系图可知原因,他们已经有一个固定的父类叫做Proxy,Java语法限定其不能再继承其他的父类

代码示例

最后以一个简单的动态代理例子结束

public class DynamicProxy {
    interface IHello{
        void sayHello();
    }

    static class Hello implements IHello{
        public void sayHello() {
            System.out.println("hello world");
        }
    }

    static class DynamicProxyTest implements InvocationHandler{
        Object originalObj;
        Object bind(Object originalObj){
            this.originalObj = originalObj;
            return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(),
                    originalObj.getClass().getInterfaces(),this);
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Welcome");
            return method.invoke(originalObj,args);
        }
    }

    public static void main(String[] args){
        //设置这个值,在程序运行完成后,可以生成代理类
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        IHello hello = (IHello) new DynamicProxyTest().bind(new Hello());
        hello.sayHello();
    }
}

程序输出为:

Welcome
hello world

注:本文是根据IBM中developerworks上的文章整理而成,原文链接https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/

Java RMI和Java Dynamic Proxy 动态代理分析 最近准备学习Hadoop RFC的模块架构学习,但是这个模块用到了比较多的java中的比较新颖的知识,比如RMI,和动态代理的了,以及还有在jdk1.4中新添加的额NIO的知识。所以决定先花一点时间,复习一下前2个模块的知识。这样对于Hadoop的RPC通信会比较了解。java RMI和Proxy动态代理我不会高谈阔论,我主要简单的举出两个例子,分析他的调用步骤,,再结合一下他的源码,达到理解,会 阅读详情

相关推荐

Docker启动安装nacos(详情讲解,全网最细)

docker安装nacos保姆级教程

ilvjiale的博客 8万+

JAVA动态代理详解

动态代理有什么作用?如何使用动态代理

biyn9的博客 1万+

java】深入分析Java反射-动态代理 proxy

1.概述 转载:深入分析Java反射(四)-动态代理JavaJava 反射机制浅析 【Javajava代理 静态代理 动态代理 proxyjava】静态代理 proxy 2.动态代理的简介 Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。Java动态代理实际上通过反射技.

九师兄 1533

Java中的动态代理

Java中的动态代理

xingfuyisheng的专栏 1260

Java动态代理技术

静态代理:在编译期确定代理类,即我们需要手动编写代理类。在这种情况下,代理类与目标类需要实现相同的接口。虽然静态代理能够增强方法,但它不够灵活,因为每次新增接口或方法都需要编写新的代理类。动态代理:在运行时动态创建代理类。Java动态代理主要基于接口进行代理,使用类和接口。动态代理通过反射机制实现,不需要手动编写代理类,能够动态地为接口生成代理类。// 定义用户服务接口// 实现接口的具体类@OverrideSystem.out.println("添加用户: " + name);

u013675821的博客 2876

java动态代理

前段时间去学习了一下RPC原理,其中提到了动态代理。特意去学习了一下,为了防止以后忘记,写下这篇博客做个记录,有不对的地方欢迎指正。 java中的常见的动态代理如Spring AOP。关于动态代理首先需要了解代理模式,根据代理类的创建时间又可以分为静态代理和动态代理。 1、代理模式 代理模式是常见的设计模式之一,Java我们通常通过new一个对象然后调用其对应的方法来访问我们需要的服务。代理模式则...

飞!!!的博客 5万+

Java 动态代理机制分析及扩展

在IBM看到了“Java 动态代理机制分析及扩展,第 1 部分”这篇文章 ,感觉很不错,就转载了,以下是原文链接 https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分...

godelgnis的博客 200

Java JDK 动态代理(AOP)使用及实现原理分析

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息 ​ 一、什么是代理? 二、Java 动态代理类 三、JDK的动态代理怎么使用? 四、动态代理怎么实现的? 五、结论 一、什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。 代理模式UML图: 简单结构示意图: 为了保持行为的...

勿忘初心 16万+

Java动态代理&&源码分析

Java动态代理&&源码分析 要了解动态代理,肯定跳不过静态代理,下面将介绍一下静态代理 1 静态代理 1.1 继承 假设一个系统中有一个Person接口,你需要使用这个接口来实现你自己需要的实体类 Person接口 public interface Person { void show(); } 系统中出现了一个警察,那我就定义一个警察类实现Person接口 Polic...

nero_claudius的博客 545

Java 两种动态代理原理分析

Java 两种动态代理原理分析

慕晨风 252

通过源码及代理动态类的源码来分析Java动态代理(jdk和cglib动态代理

文章目录一:Java动态代理的定义二:建立示例工程如下三:通过源码分析执行过程四:工程的执行结果如下: 一:Java动态代理的定义 释义:简单的说Java动态代理即为:代理对象 = 增强代码 + 目标对象(原对象)(类似实现了Python中装饰器的作用) 代理的意义:通过代理实现一系列相似操作,解决代码的臃肿问题(类似于现实生活中的中间商,为每一个买家收集好数据) 动态的释义:即该类是在代码执...

wang_da_bing的博客 515

java 动态代理机制分析及扩展

引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。通过阅读本文,读者将会对 Java 动态代理机制有更加深入的理解。本文首先从 Java 动态代理的运行机制

裴珏的专栏 718

java中的静态代理和动态代理以及Proxy的源码分析

Java架构师交流群:793825326 java版本:jdk1.8 IDE:idea2019 按照目前流行的分类,java有两种代理:静态代理,动态代理。 静态代理很简单,但灵活性很低,需要自己写代理类,实现相关接口,下面是一个静态代理的示例代码: 接口: public interface IDataService { void save(); } 实现: publi...

dap769815768的博客 273

Java动态代理的使用及原理分析

一、动态代理的使用 要使用动态代理我们要首先定义一个接口,以及一个实现了这个接口的对象,和一个实现了InvocationHandler 的类。 首先定义一个接口:public interface Subject { void doSomeThing(); } 定义一个实现了该接口的类,它将是被代理的类public class RealSubject implements Subject

BlueBerry的专栏 1119

Java动态代理的实现和源码分析

一:静态代理的实现 定义接口 /** * @description: * 加工手机的工厂 * @date: 2022/2/12 * @author: linshujie */ public interface IPhoneFactory { /** * 进行手机的定制设计 * @param design */ void makePhoneDesign(String design); } /** * @description: * 加工笔记本的工厂

Shujie 648

Java动态代理源码分析及知识点总结

Java动态代理的应用 动态代理Java中有着广泛的应用,比如Spring AOP、Hibernate数据查询、测试框架的后端mock、RPC远程调用、Java注解对象获取、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。 ...

Think Different. 272

科研——ICONIP论文修改和提交

ICONIP说明文档

Blackoutdragon的博客 6591

最新测绘资质申请三体系完整材料

2022年最新测绘资质申请三体系完整材料,公司已申请通过,这一套资料就够了。1、信息安全保障措施和管理制度体系2、技术和质量保证体系3、测绘成果和资料档案管理制度体系

上一篇: Servlet过滤器
下一篇: CGLIB(Code Generation Library)详解
danchu
博客等级 码龄16年 108粉丝 38原创
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值