代理模式—基于JDK(接口)的动态代理的使用方法
什么是代理模式?
代理模式就是给对象提供一种代理对象去控制对该对象的访问,代理类与委托类有同样的接口,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
相当显示生活中的:外卖、房产中介
优点:代理模式在访问实际对象时引入一定程度的间接性,可以做到在不修改对象代码的基础上对原对象 的功能进行修改或增强(低耦合性,高扩展性)
Java中的代理模式
-
目标类:原对象,我们需要通过代理对象控制它的访问,扩展其功能
-
代理类:代理模式产生的对象,是原对象的“替身"
静态代理
概念
就是手动写死的代理类代码,在编译时就已经将目标类和代理类确定下来
实例
以点外卖为例,顾客为目标类
public class Customer { public string order(String foodName){ return"下单"+foodName; } }
创建代理类外卖小哥
public class DeliveryClerk extends Customer{ @Override public string order(String foodName) { String result = super.order(foodName); system.out.print1n("骑士正前往取餐..."); return result+"正在派送"; } }
顾客点外卖
public class staticDemoTest { public static void main(String[ ] args) { //创建一个顾客对象 customer customer = new DeliveryClerk(); string result = customer.order("老八秘制小汉堡"); system.out.print1n(result); } }
缺点
维护依然复杂,父类或接口一发生变动,代理类就要修改。若代理类较多维护将十分困难。所以实际开发时常用动态代理
动态代理
概念
动态代理技术,是在内存中生成代理对象的一种技术。整个代理过程在内存中进行,我们不需要手写代理类的代码,而是直接在运行期,在JVM中凭空造出一个代理类对象供我们使用。
基于JDK(接口)的动态代理的使用方法
JDK有自带动态代技术,需要使用一个静态方法创建代理对象,要求相应的目标类必须实现接口
点单接口
public interface OrderInterface { public String order(String foodName) ; public void test(); public void test2(); }
目标类
public class Customer implements OrderInterface{ @override public String order(String foodName){ ... return"已下单"+foodName; } @override public void test(){} @override public void test2(){} }
测试类
实现*InvocationHandler接口*是最关键的地方,InvocationHandler中有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法。
public class DynamicTest { public static void main(String[] args) { //顾客对象 Customer customer =new customer(); //使用JDK的API工具,动态生成代理对象 orderInterface deliveryClerk =(OrderInterface) Proxy.newProxyInstance( customer.getClass().getclassLoader(), customer-getC1ass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(object proxy,Method method,object[] args) throws Throwable { if ( "order".equals(method.getName())) { Object result = method.invoke( customer,args ); ... return result + "送达"; }else{ return method.invoke(customer, args);//使用method反射调用, //原封不动调用原来的逻辑 } } } ); //调用代理对象,执行对应方法 String result = deliveryclerk.order( foodName:"老八秘制小汉堡"); System.out.println(result); deliveryClerk.test(); } }
实际上,order并没有执行,执行的是InvocationHandler中的invoke方法
所有被代理执行的方法,都是通过在InvocationHandler中的invoke方法调用的,所以我们只要在invoke方法中统一处理,就可以对所有被代理的方法进行相同的操作了。
Object invoke(Object proxy,Method method,Object[] args)
-
proxy:就是代理类对象的一个引用
-
method:对应的是出发invoke执行的方法的Method对象。假如我们调用了xxx方法,该方法触发了invoke的执行,那么,method就是xxx方法对应的反射对象(Method对象)
-
args:调用方法时传递的实际参数