目录
1、代理模式
目标对象不可访问,通过代理对象增强功能访问
生活中
房东 ===>目标对象
房屋中介 ===>代理对象
你,我 ===>客户端对象
2、代理模式的作用
控制目标对象的访问
增强功能
3、代理模式的分类
(1) 静态代理
(2) 动态代理,又为JDK动态代理,CGLib动态代理(子类代理)
4、什么是静态代理
它是代理模式的一种
它具备以下特点:
(1) 目标对象和代理对象实现同一个业务接口
(2) 目标对象必须实现接口,代理对象也要实现接口
(3) 代理对象在程序运行前就已经存在
(4) 能够半灵活的进行目标对象的切换;却无法进行功能的灵活处理,即增加或者改动功能代理对象和各个目标对象都要修改,牵一发而动全身 (使用动态代理解决此问题)
静态代理只适合:业务功能固定、目标对象随便切换这种
5、静态代理实现
业务功能 :请明星进行节目表演
明星刘德华:目标对象(无法直接访问),这是时假设不能访问
刘德华助理:代理对象(我们可以访问,他还可以跟明星对接)
我们 :客户端对象
代码实现:
业务接口
目标对象实现接口
代理对象实现接口(增强功能)
测试结果 (客户端对象)
上面代码还不能够灵活的进行目标对象的切换,需要借助面向接口编程
6、面向接口编程(重要)
6.1 什么是面向接口编程
(1)类中的成员变量设计为接口,
(2)方法的形参设计为接口,
(3)方法的返回值设计为接口,
(4)调用时接口指向实现类
6.2 面向接口编程的例子
将上面的代码改造后可以灵活的切换目标对象
改造方法:
a.在代理实现类中添加接口属性;并提供有参构造方法
b.在代理实现类的重写方法中用该属性调用接口的方法
c.然后测试的时候用接口指向代理对象;代理对象的创建时需要的接口型参数同样使用接口指向实现类,这个实现类就是new 的目标对象类
代理对象类
测试结果 (客户端对象)
总结:从在调用方法时可以灵活切换目标对象出发,需要由目标对象的参数传进代理对象,用这个参数调用方法,而这个目标对象参数又不能在代理中写死,不然就不能切换了,所以这个目标对象参数的改为接口参数,在最后调用的时候这个接口参数在指向实现类
7、动态代理
7.1 什么是动态代理
代理对象在程序运行的过程中动态在内存构建,可以灵活的进行业务功能的切换
静态代理模式下在代理对象中还得new目标对象、目标对象调用方法;而动态代理模式是利用反射创建代理对象,并且还代理出来功能和增强功能,同时用到面向接口编程使功能和目标对象的切换都十分灵活
7.2 动态代理作用
解决静态代理出现的无法进行功能的灵活处理问题
8、JDK动态代理
JDK动态代理特点:
(1)目标对象必须实现业务接口一个或多个
(2)JDK代理对象不需要实现业务接口
(3)JDK动态代理的对象在程序运行前不存在.在程序运行时动态的在内存中构建
(4)JDK动态代理灵活的进行业务功能的切换
(5)目标类中的方法(非接口中的方法)不能被代理
9、JDK动态代理的实现用到的类和接口
JDK动态代理是使用现成的工具类完成JDK动态实现
(1)Proxy类
Proxy是java.lang.reflect.Proxy包下的类。
Proxy有一个方法Proxy.newProxyInstance(.....)专门用来生成动态代理对象
(2)Method类
用来进行目标对象的方法的反射调用
(3)InvocationHandler接口
它是实现代理业务功能(方法)的。我们在调用时使用匿名内部实现。
10、动态代理实现步骤
(1)根据业务接口和目标对象创建代理工厂
(2)在工厂中定义获取动态代理的方法
(3)注意代理对象里面是包含方法的;方法是业务接口和代理对象增强功能的方法
业务接口
目标对象
代理工厂
测试结果
总结:动态代理中动态的获取代理对象使目标对象切换灵活
获取动态代理过程中的代码:Object o = method.invoke(target, args);又实现的功能的灵活切换
11、CGLib动态代理(不会用到再学)
CGLib动态代理:只有父类没有接口,子类实现代理的作用
又称为子类.通过动态的在内存中构建子类对象,重写父类的方法进行代理功能的增强.
如果目标对象没有实现接口,则只能通过CGLib子类代理来进行功能增强.
子类代理是对象字节码框架ASM来实现的.
注意:
被代理的类不能为final, 否则报错.
目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。
public Object getProxyInstance(){
//1.使用工具类
Enhancer en=new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理)对象
return en.create(); ===>返回的是子类代理对象