文章目录
一.代理模式
为其他对象提供一种代理以控制对这个对象的访问。有些情况下,一个对象不适合或者不能引用另一个对象,而代理对象可以在客户类和目标对象之前起到中介的作用。
二.使用代理模式的作用
- 功能增强:在不改变目标方法的前提下,通过代理增加额外的功能。
- 控制访问:代理类不让你直接访问目标
三.实现代理的方式
1.静态代理
(1)特点
a.代理是你手工实现的,自己创建一个Java类,代表代理类
b.你要代理的目标类是明确的
c.实现简单,容易理解
(2)举例(用户购买商品的行为)
用户:客户端类
商家:代理,代理某个商品
厂家:目标类
实现步骤:
a.创建一个接口,定义卖东西的行为
b.创建厂家类,实现步骤a中的接口
c.创建商家类,也就是代理,实现步骤a中的接口
d.创建用户类,调用商家类的方法购买东西
代理类实现的功能:
a.调用目标类的方法
b.功能增强
(3)缺点
当项目中目标类和和代理类很多的时候
a.当目标类增加时,代理类可能要成倍的增加
b.当接口中功能增加或修改时,会影响众多的代理类和目标类
2.动态代理
(1)特点
在程序运行过程中,通过jdk的反射机制,创建代理类对象,并动态的指定其目标类。
即就是一种创建java对象的能力,让你不用手动去创建代理类。
(2)实现
jdk动态代理
使用Java反射包中的类和接口实现动态代理
java.lang.reflect中有三个类/接口:InvocationHandler,Method,Proxy
a. InvocationHandler接口(调用处理器)
其中只有一个方法:invoke()
:代理对象要执行的功能代码
方法原型:public object invoke(object proxy,Method method,Object args)
参数:object proxy
: jdk创建的代理对象Method method
:目标类中的方法,是jdk提供method对象的Object[] args
:目标类中方法的参数,jdk提供的
使用:
(1)创建类实现InvocationHandler
接口
(2)重写invoke()
方法,将代理类要实现的功能写入invoke()中
b. Method类
作用:执行某个目标类的方法
method.invoke(目标对象,方法的参数);
method.invole(service,"张三");
c. Proxy类
作用:创建代理对象
方法:静态方法public static Object newProxyInstance()
//方法原型//该方法返回值就是代理对象publicstaticObjectnewProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
参数说明:
ClassLoader loader
:
类加载器,向内存中加载对象,通过反射机制获取对象的ClassLoader,是目标对象的类加载器。
//a类
a.getClass().getClassLoader();
Class<?>[] interfaces
:
接口,目标对象实现的接口,也是反射获取的
InvocationHandler h
:
是我们自己写的代理类要实现的功能
d.实现步骤
1.创建接口,定义目标类要实现的功能
packagecom.xhy.service;//目标接口//售卖u盘的功能publicinterface usbSell{floatsell(int amount);}
2.创建目标类实现接口
packagecom.xhy.factory;importcom.xhy.service.usbSell;//目标类//u盘厂家实现卖u盘的功能publicclass usbkingFactoryimplements usbSell{@Override//目标方法//amount是购买数量publicfloatsell(int amount){System.out.println("目标类执行了sell目标方法!");return65.0f;//u盘的厂家价格}}
3.创建InvocationHandler的实现类,在invoke方法中实现代理对象的功能
packagecom.xhy.handler;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;//实现InvocationHandler接口,完成代理类的功能//1.实现目标方法//2.功能增强publicclass mysellHandlerimplementsInvocationHandler{privateObject target=null;//动态代理,目标对象是动态的,是由你自己传入的,传入的对象是谁,就给谁创建代理publicmysellHandler(Object target){this.target= target;}@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{Object res=null;//1.执行目标方法//向厂家发送订单,厂家发货
res= method.invoke(target,args);//厂家的价格//2.功能增强//商家(代理)需要加价,并且赠送买家优惠券if(res!=null){Float price=(Float) res;
price= price+30;
res= price;}System.out.println("商家赠送了一张五元优惠券");//商家加价后的新价格return res;}}
4.使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型
importcom.xhy.factory.usbkingFactory;importcom.xhy.handler.mysellHandler;importcom.xhy.service.usbSell;importjava.lang.reflect.Proxy;publicclass mainShop{publicstaticvoidmain(String[] args){//创建代理对象,使用Proxy//1.创建目标类对象
usbkingFactory factory=newusbkingFactory();//2.创建InvocationHandler对象
mysellHandler handler=newmysellHandler(factory);//3.创建代理对象
usbSell proxy=(usbSell)Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
handler);//4.通过代理对象,调用目标方法//商家加价后的价格float price= proxy.sell(1);System.out.println("通过代理对象调用了目标方法(商家向厂家发送了订单):"+price);}}//呼,好累啊好累啊
5.执行结果
目标类执行了sell目标方法!
商家赠送了一张五元优惠券
通过代理对象调用了目标方法(商家向厂家发送了订单):95.0