代理模式 静态代理 动态代理:jdk动态代理 cglib动态代理
注意 :下面的代码截图 要配合文字去看 我对代码的每一步都做了解释
所以需要配合图片观看提取吗1111https://pan.baidu.com/s/1OxQSwbQ--t5Zvmwzjh1T0A?pwd=1111
这里直接把项目文件 及代码 给大家 不收费 可以下载之后对着下面的看 会增强理解
关于 代理模式:
代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介
举例子:
厂家的产品 无法直接卖给客户的时候 就需要中介 将厂家和客户联系起来 同时可以加价提高利润 类似这种就是代理模式
静态代理代码实现:
准备好 接口 接口的实现类【代理类】 目标类【也就是厂家】
建包如下:【自己发挥就行 】
封装学生类
【javabean javabean封装 就不截图了 正常一个Javabean那样去封装即可】
给它设置好空参 有参构造 以及相应的set get方法 还有自己的方法即可
封装老师类:
【javabean封装 就不截图了 正常一个Javabean那样去封装即可
这里老师的功能也就是metting会议以及test测试方法 很简单只是打印了参数
就是自己写的方法 这个做测试用的 自己发挥即可
】
接口【即老师想让学生代理他的职能】
学生代理【实现接口 拦截请求增强功能】
这个代理类 就是实现了上面的接口 可以帮助teacher类分担职能 。
这里看代码 我们对传入的参数 进行判断 这个就可以理解为功能增强 因为原本的老师类 并没有判断的功能 只有最简单的会见人员 【可以返回看一下老师类 的方法】
测试类:
可以看出来 静态代理的接口与实现类都是 我们用代码写死的,也就是说是固定的,也就是代理类是由程序写好 ,每一个代理代理一个内容,这样就会产生问题,随着代理的东西越来越多,造成资源浪费以及代码冗余
动态代理
“即可以在运行时 根据需要动态的去创建代理类 相对于静态代理的固定写死 它可以动态的根据需要自动创建代理 减少了内存资源浪费以及代码量
动态代理采用反射的机制,在运行时创建一个接口类的实例。可以统一对代码进行增强与管理。
Jdk动态代理
如何利用jdk实现动态代理
这里需要了解 Java的反射机制 以及它的jvm虚拟机才能更好的理解下面的内容
这里默认你具备基础
Jdk动态代理是利用接口 以及无参构造自动的生成代理类
必须准备
接口 以及接口的实现类
以及一个实现类去实现Proxy所需要的InvocationHandel接口
这里的InvocationHandel就是去增强代理的功能以及控制代理的行为
接口:
实现类:
InvocationHandler
这里是对代理的行为进行控制
首先定义了一个object对象 并且通过Invocation的空参构造 注入了object类 也就是我们接口的实现类 代理类
InvocationHandler的参数
- 指定代理类 也就是注入的那个代理
- 在代理实例上调用的接口方法的
Method
实例。Method
对象的声明类将是在其中声明方法的接口【调用方法进行增强】 - 包含传入代理实例上方法调用的参数值的对象数组【传入参数】
测试类:
首先拿到接口的实现类 也就是代理类
将代理注入 进行控制
利用Proxy的方法newProxyInstance动态生成一个代理类
NewProxyInstance的参数 第一个参数就是指定类加载器,由谁来加载类
第二个参数就是通过反射拿到类的接口 ,第三个参数 就是我们的代理行为控制 也就是实现了InvoationHandler的控制类
动态生成之后 再向下转体 指向生成的代理类 【由于生成的类是Object类也就是所有类的父类】
就可以调用代理的方法 从而实现动态代理
CGLIB动态代理
这个CGLB动态代理,是一个第三方库【需要导入依赖】,比起jdk动态代理来说,它不在乎是否有代理的接口,而是通过直接对目标类实现继承,从而创建代理类。相对于jdk动态代理,更加便捷,适用范围更广。
建包如上:
一个cglib的行为控制器 继承的是MethodInterceptor
用于增强以及调用方法 这个与jdk类似 我命名为CGLIBlanjieqi
CglibProxy是抽出来的一个方法主要用于创建生成代理类
Student就是目标类 即需要代理的对象
Test即测试类
Student类
MethodInterceptor:
Intercept:
参数:
- 代理对象
- * 2.方法
* 3.参数
* 4.调用代理对象【目标类的子类】或者目标对象的方法 - 不能在invokeSuper()
不能写具体的真实对象 因为会报错造成栈满 oom内存溢出
Cglibproxy
实际上也可不抽出来 单独写也行
这里抽出来只是为了减少代码 看起来美观这样
这里是写了一个泛型的静态方法
为啥用静态方法?:最先被加载 不需要创建类的实例即可调用
然后继承传入的目标类
设置回调 也就是控制代理类的行为
最后成功目标类的代理类
返回代理类
测试类:
这里可以看到 调用了我们抽出来的方法 也就是cglibProxy.getproxy
创建了代理类 我们接收一下 即可调用代理的方法了
到此就学完了Jdk与cglib的动态代理
两者的区别:
动态代理的实现方案有两种,JDK动态代理和CGLIB动态代理,区别在于JDK自带的动态代理,必须要有接口,而CGLIB动态代理有没有接口都可以。
JDK动态代理:JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口(兄弟两个拜把子模式)。
cglib动态代理:通过继承被代理的目标类(认干爹模式)实现代理,所以不需要目标类实现接口。(CGLIB 通过动态生成一个需要被代理类的子类(即被代理类作为父类),该子类重写被代理类的所有不是 final 修饰的方法,并在子类中采用方法拦截的技术拦截父类所有的方法调用,进而织入横切逻辑。)