文章目录
一.代理模式
为其他对象提供一种代理以控制对这个对象的访问。有些情况下,一个对象不适合或者不能引用另一个对象,而代理对象可以在客户类和目标对象之前起到中介的作用。
二.使用代理模式的作用
- 功能增强:在不改变目标方法的前提下,通过代理增加额外的功能。
- 控制访问:代理类不让你直接访问目标
三.实现代理的方式
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()
//方法原型
//该方法返回值就是代理对象
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
参数说明:
ClassLoader loader
:
类加载器,向内存中加载对象,通过反射机制获取对象的ClassLoader,是目标对象的类加载器。
//a类
a.getClass().getClassLoader();
Class<?>[] interfaces
:
接口,目标对象实现的接口,也是反射获取的
InvocationHandler h
:
是我们自己写的代理类要实现的功能
d.实现步骤
1.创建接口,定义目标类要实现的功能
package com.xhy.service;
//目标接口
//售卖u盘的功能
public interface usbSell {
float sell(int amount);
}
2.创建目标类实现接口
package com.xhy.factory;
import com.xhy.service.usbSell;
//目标类
//u盘厂家实现卖u盘的功能
public class usbkingFactory implements usbSell {
@Override
//目标方法
//amount是购买数量
public float sell(int amount) {
System.out.println("目标类执行了sell目标方法!");
return 65.0f; //u盘的厂家价格
}
}
3.创建InvocationHandler的实现类,在invoke方法中实现代理对象的功能
package com.xhy.handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//实现InvocationHandler接口,完成代理类的功能
//1.实现目标方法
//2.功能增强
public class mysellHandler implements InvocationHandler {
private Object target = null;
//动态代理,目标对象是动态的,是由你自己传入的,传入的对象是谁,就给谁创建代理
public mysellHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
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类的静态方法,创建代理对象,并把返回值转为接口类型
import com.xhy.factory.usbkingFactory;
import com.xhy.handler.mysellHandler;
import com.xhy.service.usbSell;
import java.lang.reflect.Proxy;
public class mainShop {
public static void main(String[] args) {
//创建代理对象,使用Proxy
//1.创建目标类对象
usbkingFactory factory = new usbkingFactory();
//2.创建InvocationHandler对象
mysellHandler handler = new mysellHandler(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