1.使用代理模式的作用
- 功能增强:在你原有的功能上,增加了额外的功能,新增的功能,叫做功能增强
- 控制访问:代理类不让你访问目标,例如商家不让用户访问厂家
2.静态代理
模拟一个用户购买U盘的行为
用户是客户端类
商家:代理,代理某个品牌的u盘
厂家:目标类
三者的关系:用户(客户端)–商家(代理)–厂家(目标)
实现步骤:
- 创建一个接口,定义卖U盘的方法,表示你的厂家和商家做的事情
- 创建厂家类,实现1步骤的接口
- 创建商家,就是代理,也需要实现1步骤的接口
- 创建客户端类,调用商家的方法买U盘
具体实现为:
- 创建一个接口
//表示功能的,厂家、商家都要完成的功能
public interface UsbSale {
//定义方法
//返回值表示一个U盘的价格
float sell(int amout);
}
- 创建厂家类继承接口
//目标类:金士顿厂家
public class UsbKingFactory implements UsbSale {
@Override
public float sell(int amout) {
return 83.0f;
}
}
- 创建商家类继承接口,需调用厂家的方法
//淘宝是一个商家,代理金士顿的销售
public class TaoBao implements UsbSale {
private UsbKingFactory factory=new UsbKingFactory();
@Override
//实现销售U盘的功能
public float sell(int amout) {
//向厂家发送订单,告诉厂家我要买U盘
float price=factory.sell(amout);//厂家的价格
price=price+20; //增强功能
return price;
}
}
- 定义主方法
public static void main(String[] args) {
TaoBao taoBao=new TaoBao();
float price=taoBao.sell(1);
System.out.println("通过淘宝的商家,购买U盘"+price);
}
3.动态代理
1.概念:在程序的执行过程中,使用jdk的反射机制创建代理,并动态的指定要代理的目标,动态代理是一种创建java对象的能力,
不用创建Taobao类,就能创建代理类对象,即不用创建代理类,可以给目标随时创建代理类
2.实现方式:
- jdk动态代理:使用java反射包中的类和接口实现动态代理的功能,反射包 java.lang.reflect,里面有三个类:InvocationHandler、Method、Proxy
- cglib动态代理:cglib是第三方的工具库,创建代理对象,cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类中同名的方法,实现功能的修改。
3.method方法
- 创建service类
public interface HelloService {
public void sayHello(String name);
}
- 创建service的实现类
public class HelloServiceImpl implements HelloService {
@Override
public void sayHello(String name) {
System.out.println("你好"+name);
}
}
- 使用反射机制调用方法
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//HelloService helloService=new HelloServiceImpl();
//helloService.sayHello("张三");
//使用反射机制执行sayhello方法,核心method(类中的方法)
HelloService target=new HelloServiceImpl();
Method method=HelloService.class.getMethod("sayHello", String.class);
//通过Method可以执行sayHello方法调用
/**
* invoke是method类中的一个方法,表示执行方法的调用
* 参数:
* 1.Object,表示要执行哪个对象的方法
* 2.Object ...args,方法执行时的参数值
* 返回值:
* Object:方法执行后的返回值
*/
//表达的意思是,执行target对象sayhello方法,参数是李四
Object ret=method.invoke(target,"李四");
}
4.InvocationHandler接口
- InvocationHandler接口,就一个方法invoke()
- invoke():表示代理对象要执行的功能代码,你的代理类要完成的功能就写在invoke()方法中
- 代理类完成的功能:调用目标方法,执行目标方法功能;功能增强,在目标方法调用时,增加功能。
- public object invoke(Object proxy,Method method,Object[] args)
- 方法原理:
参数:
Object proxy:jdk创建的代理对象,无需赋值;
Method method:目标类中的方法,jdk提供method对象;
Object[] args:目标类中方法的参数,jdk提供的 - 怎么用:
创建类实现接口InvocationHandler;
重写invoke()方法,把原来静态代理中代理类要完成的功能,写在这里
5.Method类 - 表示方法的,确切的说就是目标类中的方法
- 作用:通过Method可以执行某个目标类的方Method.invoke();
- method.invoke(目标对象,方法的参数)
Object ret=method.invoke(service2,“lisi”);
说明:method.invoke()就是用来执行目标方法的,这的invoke和上述接口中的invoke方法不同,只是恰巧同名
6.Proxy类 - 核心的对象,创建代理对象,之前创建对象都是new 类的构造方法(),现在我们是使用Proxy类的方法,代替new的使用
- 方法:静态方法 newProxyInstance()
作用是:创建代理对象,等同于静态代理中的new Taobao() - public static object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
- 参数:
ClassLoader loader 类加载器,负责向内存中加载对象的。使用反射获取对象的ClassLoader类a,a.getClass().getClassLoader()是目标对象的类加载器;
Class<?>[] interfaces:目标对象实现的接口,也是反射获取的;
InvocationHandler:我们自己写的,代理类要完成的功能
7.实现动态代理的步骤: - 创建接口,定义目标类要完成的功能
- 创建目标类实现接口
- 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能: 调用目标方法; 增加功能
- 使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型
8.实现 - 创建接口
public interface UsbSell {
float sell(int amout);
}
- 创建目标类
public class UsbKingFactory implements UsbSell {
@Override
public float sell(int amout) {
System.out.println("目标类中,执行sell目标方法");
return 85.0f;
}
}
- 实现InvocationHandler接口,实现代理类要完成的功能
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;
//其中args为参数,target为目标对象
res=method.invoke(target,args);//执行目标对象的方法
if(res!=null){
Float price=(Float)res;
price=price+25;
res=price;
}
return res;
}
}
- 创建目标对象的代理
public static void main(String[] args) {
//创建代理对象,使用Proxy
//1.创建目标对象
UsbSell factory=new UsbKingFactory();
//2.创建InvocationHandler对象
InvocationHandler 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);
}