静态代理
代理和目标实现公共的接口
1 | public interface Subject{ |
代理和目标都需要实现接口,值得注意的是,代理中方法的实现会调用目标的方法实现
1 | class Target implements Subject(){ |
动态代理
如果只有一个类有代理类,那么我们就可以用静态代理去实现,但是如果有多个类有代理类,都用静态代理的方式去实现,我们会感到无聊,因为已知一个类,要写出他的代理类,这个过程是一模一样的,我们不愿意一直重复做这种事,我们希望程序去做这种重复的事,而我们要做的,就是从中抽取公共的模式。
那么如何抽取这种公共的模式呢,答案是反射:我们知道一个方法的执行,既可以通过“ 对象.方法 ”来执行,也可以通过“ method.invoke(对象,参数)”来执行,而且invoke中可以传入方法的对象和参数。使用invoke的方式,对象可以是变量,那么就可以对不同的目标类实现代理类了。
下面这段代码就是从上述静态代理中抽取到的公共模式
1 | public interface InvocationHandler(){ |
也就是说,代理类实现invoke方法,这个invoke方法的参数中含有方法变量,然后,代理类的invoke最终会调用目标类的invoke方法。
那么我们怎么创建一个代理类呢,这里可能有人会说,直接new DynamicProxy()不就创建了吗? 但完全不是这个样子的,这里的DynamicProxy类,其实只是对目标类中的invoke方法进行了包装,并没有真正包装我们想代理的方法。为了创建一个代理类,我们需要用到java提供的一个Proxy类。
从静态代理中我们观察到:
1、代理类和目标类实现了公共的接口,也就是说我们创建代理类的时候,需要用到公共的接口,才能知道要代理哪些方法。
2、同时代理类和目标类需要用到相同的类加载器
3、同时代理类还需要二次包装的invoke方法,因为二次包装的invoke方法里面实现了我们新增加的逻辑,如果不对invoke进行二次包装,我们就无法加入新增的逻辑
知道了这些,我们完全就可以构造一个代理类了,只需调用Proxy.newProxyInstance() 就可以了,把上述三个需要的条件当作参数传进去,就可以构造出一个代理类了。
参考: