代理,一言以蔽之,就是第三方、中介的意思,比如卖家和买家之间不能直接交易,就需要一个中间人沟通两边以促成交易,和生活中的代理商、代理服务器之类其实都是同一种东西。
代理模式分为静态代理和动态代理两种,先介绍比较简单的静态代理。
静态代理
静态代理可将买家的方法调用传给代理,在代理方法内部,实际调用卖家对象的相同方法,从而完成实际方法的调用。
通过两方面要求实现静态代理
将卖家对象置于代理类中,如作为代理类的一个域代理类提供卖家的接口方法
动态代理
静态代理只能代理一个类的方法请求,那么当我们需要代理多个类的方法请求时,可用的办法有:
在代理类中重新添加多个类对象的域,然后对外提供相应的接口新建多个代理类(这个太臃肿了)
动态代理用一种更加简洁、优雅的方式解决了上述问题,即根据代理方法请求动态地创建代理,并动态地处理代理方法调用。
重要方法
Proxy静态newProxyInstance方法用来创建动态代理
loader表示类加载对象interfaces表示代理对象实现的所有方法接口h代表统一转发方法的调用处理器。
根据代码结果可知
loader只是提供一个类加载器,跟返回对象类型无关。interfaces 决定返回对象的类型是Interfaces数组里面的任意一种类型,相当于返回的Object实现了interfaces中所有的方法接口,从方法的角度和多态的定义来看,Object是interface中任意class的对象。InvocationHandler是动态代理执行调用转发的接口,要创建实现该接口的调用处理类,必须实现其抽象方法abstract Object invoke(Object proxy, Method method, Object[] args),利用反射机制使用Method.invoke()将请求转发给被代理对象(卖家)完成方法调用。
静态与动态代理对比
静态代理:顾客把请求发给代理,代理的方法实现是在其内部创建实际服务者对象,然后调用实际服务者(卖家)对象的实际方法完成顾客请求。静态代理不仅可以有选择地提供实际服务者的部分接口方法,而且能在方法体内部调用实际服务者方法前后,添加属于自己的一些操作,这点类似于继承中的super调用。 代理流程:
动态代理:顾客同样是把请求传给动态代理,但是在处理请求上,动态代理只是充当中间人或者中转站的角色,在动态代理中并不进行实际处理,只是将顾客请求(连同方法参数)转发给实际服务者,然后由实际服务者调用相应方法,完成请求。这其实有点通信中继站的意味了。 代理流程:
动态代理示例
public interface Customer {
int order(String goods, Perchasing perchasing);
boolean cancelOrder(
int orderId, Perchasing perchasing);
}
public class Lucy implements Customer {
public int order(String goods, Perchasing perchasing) {
return perchasing.acceptOrder(goods);
}
public boolean cancelOrder(
int orderId, Perchasing perchasing) {
return perchasing.cancelOrder(orderId);
}
}
public interface Perchasing {
int acceptOrder(String goods);
boolean cancelOrder(
int orderId);
}
public class WomanInUK implements Perchasing {
private ArrayList<String> goodsList =
new ArrayList<String>();
public int acceptOrder(String goods) {
goodsList.add(goods);
int orderId = goodsList.indexOf(goods) +
1;
System.out.println(
"Proxy : " +
this.getClass().getName() +
"\ngoods : "
+ goods +
", Order " + orderId);
return orderId;
}
public boolean cancelOrder(
int orderId) {
goodsList.remove(orderId -
1);
System.out.println(
"Proxy : "
+
this.getClass().getName() +
"\nCacnel Order : " + orderId);
return true;
}
}
public class PerchasingDynamicProxy implements InvocationHandler {
private Object proxied;
public PerchasingDynamicProxy(Object proxied){
this.proxied = proxied;
}
public Object
invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println(
"proxy : " + proxy.getClass() +
"\nmethod :"
+ method +
"\nargs :" + args);
if (args !=
null) {
for(Object arg : args)
System.out.println(
"Method Parameter : " + arg);
}
System.out.println(
"-------------Invoke Dynamic Proxy-----------");
return method.invoke(proxied, args);
}
}
public class OverseasPerchasing {
public static void main(String[] args) {
Lucy lucy =
new Lucy();
WomanInUK realProxy =
new WomanInUK();
lucy.order(
"MacBook Pro", realProxy);
System.out.println(
"---------------Order----------------");
Perchasing perchasingProxy = (Perchasing) Proxy.newProxyInstance(
Customer.class.getClassLoader(),
new Class[]
{Perchasing.class, Customer.class},
new PerchasingDynamicProxy(realProxy));
int order = lucy.order(
"SurfaceBook", perchasingProxy);
System.out.println(
"-----------Cacnel Orders-------------");
if (lucy.cancelOrder(order, perchasingProxy)) {
System.out.println(
"Canceling Orders Succeeds! ");
}
}
}
----------
Proxy : com.hwl.proxy.WomanInUK
goods : MacBook Pro, Order
1
---------------Order----------------
proxy : class com.sun.proxy.$Proxy0
method :
public abstract int com.hwl.proxy.Perchasing.
acceptOrder(java.lang.String)
args :[Ljava.lang.Object;@
232204a1
Method Parameter : SurfaceBook
-------------Invoke Dynamic Proxy-----------
Proxy : com.hwl.proxy.WomanInUK
goods : SurfaceBook, Order
2
-----------Cacnel Orders-------------
proxy : class com.sun.proxy.$Proxy0
method :
public abstract boolean com.hwl.proxy.Perchasing.
cancelOrder(
int)
args :[Ljava.lang.Object;@
4aa298b7
Method Parameter :
2
-------------Invoke Dynamic Proxy-----------
Proxy : com.hwl.proxy.WomanInUK
Cacnel Order :
2
Canceling Orders Succeeds!