开发者学堂课程【Scala 核心编程 - 进阶:动态代理的原理和保护代理的概念】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/610/detail/9147
动态代理的原理和保护代理的概念
内容介绍:
一、动态代理概念
二、保护代理
一、动态代理概念
1. 动态代理概念的引入
在学习 Java 反射的时候已经了解了动态代理和静态代理,动态代理是开发中经常用到的一种代理模式。
现有一个对象 RealSubject,要实现对这个对象操作的控制,不希望别人直接来调用,而是针对不同的人,给予不同的调用权限
2、动态代理示意图
现有这样的场景,右侧为被代理的类(被代理的对象),传统的调用方法一般是:
val obj =new 类() obj.xxx,但是在某些情况不允许这样调用,比如一个被代理的类person具有setName、getXXX、setscore等几个方法,现有两种应用场景,第一种希望A类用户能够调用实例化person类,但是只能够调用其中的 setName 方法,其他方法不可调用,而B类用户可以去调用person中的setscore和getXXX方法,不能调用其他方法。
即A和B两种用户,对person的方法调用权限是不一样的,面对这种需求可能有些同学提出将其设置为私有类型,但是设置成私有类型后,B类用户也无法进行调用,因为私有不针对用户种类,无法实现权限的控制,因此不能通过私有的方式来满足需求。
- 解决方法
收回调用的箭头,在中间添加一个代理,通过动态代理创建一个代理对象,用来替代被调用的对象,使用反射机制实现对调用权限的控制,这就是动态代理的核心问题。
创建代理对象帮助我们完成调用,不再是直接调用,而是通过代理模式针对A用户返回一种代理对象,针对B用户返回另一种代理对象,然后即可满足对调用权限的控制,针对A类用户返回的代理对象只能调 setName 方法,针对B用户则只能调用 setscore 和 getXXX 方法。将来同学们遇到这种类似的需求时,就可以去应用代理去解决问题。
3、动态代理的实现
User为刚才所讲的A类用户或者B类用户,不是直接实例化RealSubject,而是添加一个subject的接口,让代理和真正被调的对象实现这个接口,代理和 InvocationHandler共同构成动态代理来帮我们返回代理对象,用反射的 invoke 来判断到底应该调用哪些方法,即Proxy和Invocation Handler 共同构成代理。
总结:
动态代理是指运行时动态的创建代理类(对象),也就是RealSubject的代理,因为真正调用的其实是RealSubject,并将方法调用转发到指定的地方。
- Proxy和 InvocationHandler 组合充当代理的角色;
- RealSubject是一个实际对象,它实现接口Subject;
- 在使用时,我们不希望直接访问RealSubject的对象,比如:我们对这个对象的访问是有控制的比如有些方法可以调用,有些方法不可以调用;
- 我们使用动态代理,在程序中通过动态代理创建RealSubject,并完成调用;
- 动态代理可以根据需要,创建多种组合
- Proxy也会实现Subject接口的方法,因此,使用Proxy+invocation可以完成对RealSubject的动态调用。
- 但是通过Proxy调用RealSubject方法是否成功,是由InvocationHandler来控制的。(这里其实就是保护代理)
理解:
我们在写反射的时候,会实现一个方法,里面就有invoke这个方法,所谓动态代理可以这样理解,创建一个代理对象管代披调用的真实对象使用反射实现控制。
二、保护代理
动态代理已经包含了保护代理的概念,有些面试官可能会问到动态代理实现的机制,这个时候就可以把刚才的图进行简单的描述,有时也有可能会问到保护代理的概念,所以我们对保护代理进行简单的讲解。
保护代理:
通过前面的分析:大家可以看出动态代理其实就体现出保护优理,即代理时,对被代理的对象(类)的哪些方法可以调用,哪些方法不能调用在
InvocationHandler 可以控制。因此动态代理就体现(实现)了保护代理的效果。