avatar

Catalog
从静态代理到动态代理

静态代理

代理和目标实现公共的接口

java
1
2
3
public interface Subject{
doSomething();
}

代理和目标都需要实现接口,值得注意的是,代理中方法的实现会调用目标的方法实现

java
1
2
3
4
5
6
7
8
9
10
11
12
13
class Target implements Subject(){
@override
doSomething(){

}
}
class StaticProxy implements Subject(){
Target target =new Target();
@override
doSomething(){
target.doSomething();
}
}

动态代理

如果只有一个类有代理类,那么我们就可以用静态代理去实现,但是如果有多个类有代理类,都用静态代理的方式去实现,我们会感到无聊,因为已知一个类,要写出他的代理类,这个过程是一模一样的,我们不愿意一直重复做这种事,我们希望程序去做这种重复的事,而我们要做的,就是从中抽取公共的模式。

那么如何抽取这种公共的模式呢,答案是反射:我们知道一个方法的执行,既可以通过“ 对象.方法 ”来执行,也可以通过“ method.invoke(对象,参数)”来执行,而且invoke中可以传入方法的对象和参数。使用invoke的方式,对象可以是变量,那么就可以对不同的目标类实现代理类了。

下面这段代码就是从上述静态代理中抽取到的公共模式

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

class DynamicProxy implements InvocationHandler
{
private Object target;
public DynamicProxy(Object target)
{
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
增加的逻辑;
method.invoke(target, args);
}

也就是说,代理类实现invoke方法,这个invoke方法的参数中含有方法变量,然后,代理类的invoke最终会调用目标类的invoke方法。

那么我们怎么创建一个代理类呢,这里可能有人会说,直接new DynamicProxy()不就创建了吗? 但完全不是这个样子的,这里的DynamicProxy类,其实只是对目标类中的invoke方法进行了包装,并没有真正包装我们想代理的方法。为了创建一个代理类,我们需要用到java提供的一个Proxy类。

从静态代理中我们观察到:

1、代理类和目标类实现了公共的接口,也就是说我们创建代理类的时候,需要用到公共的接口,才能知道要代理哪些方法。

2、同时代理类和目标类需要用到相同的类加载器

3、同时代理类还需要二次包装的invoke方法,因为二次包装的invoke方法里面实现了我们新增加的逻辑,如果不对invoke进行二次包装,我们就无法加入新增的逻辑

知道了这些,我们完全就可以构造一个代理类了,只需调用Proxy.newProxyInstance() 就可以了,把上述三个需要的条件当作参数传进去,就可以构造出一个代理类了。

参考:

https://www.cnblogs.com/zhangchengzi/p/9713807.html

https://www.zhihu.com/question/20794107/answer/658139129

Author: realLiuSir
Link: http://yoursite.com/2020/04/03/%E4%BB%8E%E9%9D%99%E6%80%81%E4%BB%A3%E7%90%86%E5%88%B0%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶