代理模式—基于JDK(接口)的动态代理的使用方法
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
什么是代理模式?
代理模式就是给对象提供一种代理对象去控制对该对象的访问,代理类与委托类有同样的接口,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
相当显示生活中的:外卖、房产中介
优点: 代理模式在访问实际对象时引入一定程度的间接性,可以做到在不修改对象代码的基础上对原对象 的功能进行修改或增强(低耦合性,高扩展性)
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:调用方法时传递的实际参数