运行结果如下:
网络异常,图片无法展示
|
接着可以打开看看 $Proxy0 这个动态代理类:
网络异常,图片无法展示
|
static代码块中获取代理方法,然后利用反射调用动态代理类的方法。看着比较简单,接着看下背后的原理。
② JDK动态代理的实现原理
跟下Proxy的 newProxyInstance()
方法:
网络异常,图片无法展示
|
先跟下 getProxyClass0()
查找或生成代理类的方法:
网络异常,图片无法展示
|
跟 proxyClassCache.get()
→ WeakCache.get()
→ ProxyClassFactory.apply()
网络异常,图片无法展示
|
定位到了生成字节码的方法: ProxyGenerator.generateProxyClass()
:
网络异常,图片无法展示
|
定位到 generateClassFile(),分为三步:
1)为所有方法生成代理调度代码,将代理方法对象集合起来
网络异常,图片无法展示
|
2)为类中的方法生成字段信息和方法信息
网络异常,图片无法展示
|
3)生成最终类文件
网络异常,图片无法展示
|
以上就是 $Proxy0 类的大概生成流程,了解下即可,具体的细节真的是繁琐...
0x3、CGLIB动态代理示例
JDK动态代理需要定义一个接口,实现类实现接口中的方法,如果实现类不能实现接口,就没办法用这种方式了。
而CGLIB动态代理使用 字节码增强技术,对编译好的class字节码文件生成该类的子类,利用多态,调用父类中的方法,实际上调用的子类中的对应方法。因为需要继承,所以被代理类或方法不要用final关键字修饰。
CGLIB需要用到两个jar包,asm.jar
→ 字节码增强技术的核心,cglib.jar
→ CGLIB库,可以分开下载导入,也可以直接下载 cglib Git仓库 的 cglib-nodep.jar 包。
代码示例如下:
// 被代理类 public class Store { public void sell(String thing) { System.out.println("商家卖:" + thing); } public void close() { System.out.println("关门大吉"); } } // 方法增强类 public class StoreTrade implements MethodInterceptor { /** * @param o 要增强的对象 * @param method 要拦截的方法 * @param objects 方法中的参数 * @param methodProxy 对方法的处理 */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable{ System.out.println("Before Method === " + method.getName()); System.out.println("传入的方法参数:" + Arrays.toString(objects)); methodProxy.invokeSuper(o, objects); System.out.println("After Method === " + method.getName()); return null; } } // 测试用例 public class StoreTest { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); // 增强类对象 enhancer.setSuperclass(Store.class); // 设置要增强的类 StoreTrade store = new StoreTrade(); enhancer.setCallback(store); // 设置要增强的方法 Store s = (Store) enhancer.create(); // 生成增强过的子类encodings s.sell("牛奶"); s.close(); } }
运行结果示例:
网络异常,图片无法展示
|
会用就差不多了,源码就不去看了,肯定是个大骨头...