<p style="clear:both;min-height:1em;color:rgb(62,62,62);font-family:'Helvetica Neue',Helvetica,'Hiragino Sans GB','Microsoft YaHei',Arial,sans-serif;font-size:18px;">
<span style="color:rgb(123,12,0);">1. 什么是代理
<p style="clear:both;min-height:1em;color:rgb(62,sans-serif;font-size:18px;">
-
修改委托类代码的情况下能够做一些额外的处理。
代码中定义的。 通常情况下,静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类。下面我们用Vendor类代表生产厂家,BusinessAgent类代表微商代理,来介绍下静态代理的简单实现,委托类和代理类都实现了Sell接口。静态类的实现包括:一个interface,两个实现该interface的class。如下:
/**
- Created by cxh on 17/3/26.
- 微商和委托方的公共接口
*/
public interface Sell {
void sell();
void add();
}
<p style="clear:both;min-height:1em;color:rgb(62,sans-serif;font-size:18px;">
Vendor类的定义如下:
<p style="clear:both;min-height:1em;color:rgb(62,sans-serif;font-size:18px;">
/**
- Created by cxh on 17/3/26.
- 委托方实现接口方法
*/
public class Vender implements Sell{
@Override
public void sell(){
System.out.println("in sell method");
}
@Override
public void add(){
System.out.println("in add method");
}
}
<p style="clear:both;min-height:1em;color:rgb(62,sans-serif;font-size:18px;">
代理类BusinessAgent的定义如下:
<p style="clear:both;min-height:1em;color:rgb(62,sans-serif;font-size:18px;">
/**
-
Created by cxh on 17/3/26.
-
代理类实现接口sell方法
*/
public class BusinessAgent implements Sell{
private Vender vender;
public BusinessAgent(Vender v){
this.vender=v;
}
@Override
public void sell(){
vender.sell();
}
@Override
public void add(){
vender.add();
}
}
<p style="clear:both;min-height:1em;color:rgb(62,sans-serif;font-size:18px;">
从BusinessAgent类的定义我们可以了解到,静态代理可以通过聚合来实现,让代理类持有一个委托类的引用即可。
<p style="clear:both;min-height:1em;color:rgb(62,sans-serif;font-size:18px;">
下面我们考虑一下这个需求:给Vendor类增加一个过滤功能,只卖货给大学生。通过静态代理,我们无需修改Vendor类的代码就可以实现,只需在BusinessAgent类中的sell方法中添加一个判断即可如下所示:
<p style="clear:both;min-height:1em;color:rgb(62,sans-serif;font-size:18px;">
修改委托类代码的情况下能够做一些额外的处理。静态代理的局限在于运行前必须编写好代理类,下面我们重点来介绍下运行时生成代理类的动态代理方式。
代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。这么说比较抽象,下面我们结合一个实例来介绍一下动态代理的这个优势是怎么体现的。
方法。这个接口的源码定义如下:
名称我们就可以知道,实现了这个接口的中介类用做“调用处理器”。当我们调用代理类对象的方法时,这个“调用”会转送到invoke方法中,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,这样我们可以在invoke方法中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)。因此我们只需在中介类的invoke方法实现中输出“before”,然后调用委托类的invoke方法,再输出“after”。下面我们来一步一步具体实现它。包括了4个文件:1个sell接口;1个vender类,实现了sell接口的委托方;1个代理类DynamicProxy,实现了
java.lang.reflect.InvocationHandler接口的类;一个测试类MainTest。
代码如下:
/**
- Created by cxh on 17/3/26.
- 委托方/代理 共同大家的接口
*/
public interface Sell {
void sell();
void add();
}
<pre style="font-family:Menlo;"><span style="font-size:14px;">4.2 vender类,委托方代码如下:
<pre style="font-family:Menlo;"><span style="font-size:14px;">
/**
- Created by cxh on 17/3/26.
- 委托方,供应商
*/
public class Vender implements Sell {
public void sell(){
System.out.println("this is sell method");
}
public void add(){
System.out.println("this is add method");
}
}
<pre style="font-family:Menlo;"><span style="font-size:14px;">4.3 代理类<span style="color:rgb(62,sans-serif;font-size:18px;">DynamicProxy代码如下:
<pre style="font-family:Menlo;"><span style="font-size:14px;"><span style="color:rgb(62,sans-serif;font-size:18px;">
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
- Created by cxh on 17/3/26.
- 中介类,调用处理器
*/
public class DynamicProxy implements InvocationHandler {
private Object obj;//obj为动态代理对象
public DynamicProxy(Object obje){this.obj=obje;}
//参数说明:object为代理方对象,method调用的代理方的方法,args为调用的代理方方法的参数
@Override
public Object invoke(Object object,Object[] args) throws Throwable{
System.out.println("before");
Object result=method.invoke(obj,args);
System.out.println("after");
return result;
}
}
<pre style="font-family:Menlo;"><span style="font-size:14px;"><span style="color:rgb(62,sans-serif;font-size:18px;">4.4 测试类MainTest代码如下:
<pre style="font-family:Menlo;"><span style="font-size:14px;"><span style="color:rgb(62,sans-serif;font-size:18px;">
import java.lang.reflect.Proxy;
/**
-
Created by cxh on 17/3/26.
*/
public class MainTest {
public static void main(String[] args) {
//创建中介类实类
DynamicProxy dynamicProxy=new DynamicProxy(new Vender());
//<a href="/tag/huoqu/" target="_blank" class="keywords">获取</a>代理类实例sell
//在下<a href="/tag/daima/" target="_blank" class="keywords">代码</a>中,我们<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a>Proxy类的newProxyInstance<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>来<a href="/tag/huoqu/" target="_blank" class="keywords">获取</a>一个代理类实例。
// 这个代理类实现了我们指定的接口并且会把<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a><a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a>分发到指定的<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a>处理器。
Sell sell=(Sell)(Proxy.newProxyInstance(Sell.class.getClassLoader(),new Class[]{Sell.class},dynamicProxy));
sell.add();
sell.sell();
}
}
<pre style="font-family:Menlo;"><span style="font-size:14px;"><span style="color:rgb(62,sans-serif;font-size:18px;">4.5 运行结果如下:
<pre style="font-family:Menlo;"><span style="font-size:14px;"><span style="color:rgb(62,sans-serif;font-size:18px;">
Process finished with exit code 0