Java动态代理
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。
静态代理
创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时使其也实现这个接口。在代理类中持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。
简而言之就是接口和实现接口的类,接口定义了某种方法,实现接口的类需要去重写方法。
但是静态代理只能代理一个类,如果有多个类需要代理就不能用静态代理实现了,这时候要用动态代理来实现。动态代理可以很方便的对代理类的函数进行统一的处理(invoke),而不是修改每个代理类的函数,更灵活和扩展。
与静态代理相比,动态代理是在运行时动态生成一个代理类(Java反射机制可以在运行时生成类),该类可以对目标对象的方法进行功能增强。之前学习Java反射机制时提到了反射机制可以生成动态代理,
动态代理
网上看Java动态代理貌似有两种,基于JDK的动态代理和基于CGILB的动态代理,我们在这里只学习下JDK的动态代理,如果后面要用到另一种,再去学习。JDK动态代理有两个重要的类或接口, InvocationHandler(Interface)和Proxy(Class),实现我们动态代理必须用到它们。先来看下这两个类。
InvocationHandler(Interface)
先来看下,里面的源码是我加的注释
1 | package java.lang.reflect; |
Proxy(Class)
Proxy这个类的作用就是用来动态创建一个代理对象的类。如下图,可以看到Proxy实现了Serializable接口,他有很多成员变量和方法,其中newProxyInstance是需要经常用到的,所以就分析它好了。
1 | public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h) |
loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
实例:
newProxyInstance需要三个参数(目标接口,实现目标接口的子类,扩展处理器-处理目标接口的handler),首先把三个参数准备好分别是ImpTest.class.getClassLoader()、ImpTest.class.getInterfaces()和handler,测试的时候遇到一个错误,就是代理类必须要实现接口,我们代理的时候是代理接口的方法,这里是Test.test()和Test.test1(),所以当我们调用proxy.test()和proxy.test1()都会去调用handler.invoker()方法。
所以就是说在这个实例中,我们是用handler.invoker()去代理Test接口的所有方法。
1 | import java.lang.reflect.InvocationHandler; |
运行结果:
动态代理具体步骤:
- 通过实现 InvocationHandler 接口创建自己的调用处理器;
- 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
- 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
- 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
参考链接:
https://www.cnblogs.com/gonjan-blog/p/6685611.html
https://blog.csdn.net/weixin_40558287/article/details/103058052
https://blog.csdn.net/qq_32532321/article/details/81874990
https://www.jianshu.com/p/9bcac608c714