先理解代理和目标的概念:
举例来说:
金士顿厂家生产U盘但是不直接卖给用户,是经过代理商来卖的
代理商可以是淘宝,可以是京东,可以是拼多多
那么此时,淘宝,京东,拼多多就是代理,
金士顿厂商就是目标,
先看静态代理:
静态代理的3个步骤:
1)定义一个接口,接口中包含目标和代理都要实现的方法
2)目标类实现接口
3)代理类包含目标对象,调用目标对象的方法,并增强实现
具体操作如下:
1,定义一个接口,接口里面定义了目标厂家和代理商要实现的功能
比如这里的目标厂商金士顿和代理商淘宝都要实现卖U盘的功能
public interface usbsell {
void sell();
}
2,目标类实现接口
public class kingstonFactory implements usbsell {
@Override
public void sell() {
System.out.println("目标类:工厂卖U盘 85元一个");
}
}
3.代理类包含目标对象,并利用目标对象 调用目标对象的方法,并且可增强功能
public class taobao implements usbsell{
//代理类要想调用目标类的方法 就要包含目标对象
kingstonFactory kf=new kingstonFactory();
public void sell() {
//利用目标对象 调用目标对象里面的方法
kf.sell();
//增强实现
System.out.println("增强实现,淘宝给买U盘的用户送一个小礼品");
}
}
4测试
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
taobao tb=new taobao();
tb.sell();
}
}
输出结果:
静态代理的优缺点:
优点:简单
缺点:
静态代理的3个步骤:
1)定义一个接口,接口中包含目标和代理都要实现的方法
2)目标类实现接口
3)代理类包含目标对象,调用目标对象的方法,并增强实现
由静态代理的3个步骤可知:
如果目标工厂有多个,那么就要创建多个代理类
比如除了金士顿,还有三星,闪迪卖U盘,这些厂家都是目标,那么不仅要创建这三个目标类,还要创建三个代理类
代码的重用性不强
动态代理
动态代理的步骤:
1定义一个公共接口,接口中定义了目标类和代理类都要实现的方法;比如代理商和工厂都要实现卖U盘接口
public interface factorySell {
void sell();
}
2 目标类实现这个接口,
public class kingstonFactory implements factorySell{
@Override
public void sell() {
System.out.println("目标方法:金士顿原厂卖U盘85元一个");
}
}
3 定义一个 myhandler 实现 InvocationHandler接口,
接口里面有一个invoke方法,在这个方法里面通过反射调用目标类中的方法,并且可以增强实现。
值得注意的是,这个handler接口的实现类,要通过构造方法来从外界获取目标对象target,这为下面invoke 方法中 method.invoke(target, args);打下了基础
,这样,你想要执行哪个代理类的sell方法,就传那个代理类的对象。
public class myhandler implements InvocationHandler{
//用构造方法接收传入的目标对象
Object target=null;
myhandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通过反射调用目标对象的方法
method.invoke(target, args);
//增强实现
System.out.println("代理类对原厂方法进行了增强,一个U盘100元");
return null;
}
}
这个method.invoke(target, args);要搞清楚,
method指的是公共接口中定义的方法,本例中是usbsell接口中定义的方法
target指的是由程序员指定的,本例中是通过myhandler类的构造函数,接收到的目标对象,也就是金士顿工厂对象
搞清楚这一点,才能搞清楚当invoke执行时,到底是哪个类的哪个方法被调用了,很明显是目标类中实现了的公共接口中的方法被调用了,比如目标类(金士顿工厂类)实现了usbsell接口中的sell方法,
4调用Proxy中的静态方法 newProxyInstance来实现动态代理
Proxy.newProxyInstance(ClassLoader loader, //目标类对应的类加载器
Class<?>[] interfaces, //目标类对应的接口,这里指的就是卖U盘的接口
InvocationHandler h // 实现了InvocationHandler接口的那个类的对象
)
图1:
Proxy中的静态方法 newProxyInstance返回一个代理对象,这个代理对象中包含上图中, newProxyInstance函数的第二个参数 接口中定义的方法,例如本例中的接口usbsell中就定义了一个方法sell(),
那么调用newProxyInstance返回一个代理对象proxy,这个代理对象就可以直接调用sell方法,proxy.sell();
但是值得注意的是,调用这个sell方法就像启动了InvocationHandler接口中的invoke方法一样,不仅会调用目标对象的sell 方法,还会调用增强方法,也就是把invoke中的方法都执行一遍,这是很奇怪的,明明只调用了sell方法,却把invoke方法执行了一遍
测试类:
**public class test {
public static void main(String[] args) {
kingstonFactory mubiaoleiDuixiang=new kingstonFactory();
factorySell dailileiDX=(factorySell) Proxy.newProxyInstance(mubiaoleiDuixiang.getClass().getClassLoader(),
mubiaoleiDuixiang.getClass().getInterfaces(),
new myhandler(mubiaoleiDuixiang));
dailileiDX.sell();
}
}**
动态代理的优点:
1.相比于静态代理,静态代理创建一个目标类之后,还需要创建一个代理类,
而动态代理只需要创建目标类,而不需要创建代理类了,这样一来,如果你在接口里面添加一个方法,那么只需要改动一下目标类即可,不需要像静态代理那样,目标类和代理类都要改。
2,如果有多个代理对象,每个代理对象增强实现的方法不一样,比如代理类不仅有淘宝,还有京东,微商,拼多多,每个代理要实现的增强不一样,那么