动态代理:在程序运行时,通过反射机制动态创建而成。
用到的两个类, java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy
示例
UserService.java
|
|
UserServiceImpl.java 委托类
|
|
ServiceInvocationHandler.java
|
|
JdkProxyTest.java 测试类
|
|
执行结果
|
|
JDK动态代理的用法:
- 一个接口
- 一个接口的实现类, 用作委托类
- 一个实现
java.lang.reflect.InvocationHandler
的类, 这个类有个成员变量(上面的接口实现类), 此类必须实现invoke(Object proxy, Method method, Object[] args)
方法 - 必须要有创建代理类的操作, 是上述代码的
UserService userServiceProxy = (UserService) handler.getProxy();
的部分, 生成的代理类继承Proxy, 实现委托类实现的接口
代理类的字节码是从哪里生成的?
进入java.lang.reflect.Proxy.ProxyClassFactory#apply()
方法,最终是通过调用sun.misc.ProxyGenerator#generateProxyClass(final String proxyName, Class<?>[] interfaces, int accessFlags)
方法生成byte[],然后调用方法java.lang.reflect.Proxy#defineClass0
,由类加载器加载生成对应的Class对象
到底生成了怎样的字节码? 我们可以自己调用sun.misc.ProxyGenerator#generateProxyClass(final String proxyName, Class<?>[] interfaces, int accessFlags)
这个方法去生成代理类的字节码,然后反编译看看
|
|
动态生成的Service的实现类反编译后内容如下
|
|
看到生成的构造函数需要一个InvocationHandler的实例,这个实例是怎么传递给ProxyService的构造函数的呢?是通过java.lang.reflect.Proxy#newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
这个方法,具体代码如下:
|
|
Service接口的每个方法实现里都有类似下面的代码
|
|
总结
JDK动态代理只做了两件事:
- Look up or generate the designated proxy class.(查找或生成指定的代理类)
- Invoke its constructor with the designated invocation handler.(使用指定的调用处理程序调用它的构造函数)