java代理模式
1.0关于代理
- 我们通常所说的java代理模式总共分为三种,分为:静态代理、jdk动态代理(接口代理)、cglib动态代理(子类代理)技术是整个java技术中最重要的一个技术,是java框架的基础,在Spring等框架中运用了大量的代理技术。
- 在实际开发的过程中,我们经常调用别人写的代码完成业务需求开发,很多时候,我们想在原来实现的基础上稍微做一些调整扩展,但是又不能修改别人的代理,怎么办呢?代理可以解决。
- 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象,这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
1.1 代理模式
假如我们要去买电脑,我们通常需要去找电脑代理商购买,电脑代理商去电脑工厂提货,电脑代理商可以赚取中间的差价。 假如我们想买火车票,我们可以直接去12306网站买票。可是太难抢到票了,于是我们去找火车票的黄牛,让黄牛帮我们去12306买票,黄牛买到票再加价卖给我们,赚取中间的差价。
你买电脑 -> 电脑代理商 -> 电脑工厂
你买火车票 -> 黄牛 -> 12306
调用者 代理对象 真正干活的目标对象我们发现代理对象和真正干活的目标都具有相同的功能(卖电脑/卖票),代理可以在中间赚取差价(增强功能)。
1.2 代理模式的作用
- 代理对象可以在调用者和目标对象之间起到中介的作用。代理对象可以对目标对象的功能进行增强。
- 代理模式的作用:增强某一对象的某一个功能。
1.3代理模式涉及到四个要素
- 调用者:你。
- 代理对象:联想电脑代理商/黄牛
- 目标对象(被代理对象):电脑工厂/12306
- 抽象对象:代理对象和目标对象都共有的接口,保证代理对象和真实对象都有相应的方法,如电脑代理商和电脑工厂都需要有卖电脑的功能。
2.1 什么是动态代理
- 在程序运行的过程中,动态创建出代理对象。
2.2 动态代理相应的API
- Proxy类:static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
- 作用:生成实现指定接口的代理对象。
- 参数说明:
- loader参数:目标对象的类加载器
- interfaces:代理对象实现的接口数组
- h: 具体的代理操作,InvocationHandler是一个接口,需要传入一个实现了此接口的实现类。
- 返回值:实现指定接口的代理对象。
- InvocationHandler接口
- Object invoke(Object proxy, Method method, Object[] args)
- 作用:在这个方法中实现对真实方法的增强。
- 参数说明:
- proxy:即方法newProxyInstance()方法返回的代理对象,该对象一般不要在invoke方法中使用。
- method: 代理对象调用的方法对象。
- args:代理对象调用方法时传递的参数。
- 返回值:是真实对象方法的返回值。
2.3 需求
模拟电脑代理商与电脑厂商之间的代理关系,最终实现代理商中间赚取差价。
- 设计模式:解决这一类问题的固定步骤:
- 固定步骤:
- 处理器内部一定要维护一个被代理对象。
- 一定需要在invoke方法内部获取方法名
- 如果不需要被代理的方法,直接让该方法执行即可,并且使用被代理对象去执行。
- 如果需要被代理的方法,那么就写上自己的业务逻辑即可。
1.公共接口
package com.sunny.proxy;
/**
* 卖电脑、修电脑接口
*/
public interface Provide {
public void sellComputer(double money);
public void repairComputer(double money);
}
2.电脑厂商类
package com.sunny.proxy;
public class ComputerFactory implements Provide {
@Override
public void sellComputer(double money) {
System.out.println("电脑厂商收到了"+money+"钱,电脑发货...");
}
@Override
public void repairComputer(double money) {
System.out.println("电脑厂商收到了"+money+"钱,维修电脑...");
}
}
3.电脑厂商代理类
package com.sunny.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ComputerProxy {
/**
* 电脑代理商
* 动态代理的作用:增强一个对象的某个方法。
* 动态代理涉及的类与方法:
* Obejct proxy = Proxy.newProxyInstanceI(,A.class,B.clsss); 动态创建一个对象并且实现你指定的接口。
* newProxyInstance(ClassLoader loader, Class[] interfaces, reflect.InvocationHandler h)
* loader: 类加载器,
interfaces : 指定代理对象需要实现的接口数组。
InvocationHandler : 处理器。
invoke(Object proxy, Method method, Object[] args)
proxy : 当前的代理对象
method: 当前调用的方法
args: 当前传入的参数.
*/
public static void main(String[] args) {
/**
* 得到一个电脑厂商的代理对象。动态代理对象帮你动态生成一个对象,实现了你指定的接口的方法,
* 但是实现的时候全部都是空实现,如果需要实现具体的方法,那么需要处理器的invoke方法去实现。
*/
Provide proxy = (Provide) Proxy.newProxyInstance(ComputerProxy.class.getClassLoader(), new Class[]{Provide.class}, new MyHandler());
//代理对象只能使用接口定义的方法
proxy.sellComputer(10000);
}
}
class MyHandler implements InvocationHandler{
//处理器内部一定要维护一个被代理对象
ComputerFactory factory = new ComputerFactory();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取当前调用的方法名
String methodName = method.getName();
//需求:代理你卖电脑的功能
if("sellComputer".equalsIgnoreCase(methodName)){
//代理你的功能
double totalPrice = (double) args[0];
double price = totalPrice*0.7;
System.out.println("代理商收入了:"+totalPrice+"给了电脑厂商:"+price);
}else {
//不需要代理
method.invoke(factory,args);
}
return null;
}
}
卖电脑功能,需要代理
修电脑功能,不需要代理,走else,结果为:电脑厂商收到了10000.0钱,维修电脑...