0. 原理分析

a). 自定义实现InvocationHandler类,实现代理类执行时的invoke方法
b). 使用Proxy.newProxyInstance生成接口的代理类(入参还包括InvocationHandler)
c). 所有的proxyImpl.methodName都会被invoke方法拦截
d). 备注: 推荐反编译$Proxy0.查看
1 -- 设置系统参数以保存中间态生成的class文件, 文件名类似 $Proxy0.class
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true")
2 -- $Proxy0.class所在的目录 System.getProperty("user.dir")/com/sun/proxy/, 即执行java命令的目录下
IDEA和eclipse中是工程的根目录

1. 示例

1.1 示例1--直接代理接口(Mybatis的Mapper)

TestInterface.java
public interface TestInterface {
public void saySomething(String thing);
}
InvokeMethodClass.java
public class InvokeMethodClass implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入invoke方法!");
//method.invoke("zzzzzz");
System.out.println("invoke执行结束");
return null;
} public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); //保存中间态的代理类class到文件
TestInterface tt = (TestInterface) Proxy.newProxyInstance(TestInterface.class.getClassLoader(), new Class[]{TestInterface.class}, new InvokeMethodClass());
tt.saySomething("sssssss");
}
}

执行:

java -cp G:\practice\idea-new\ideaMaven\target\classes  test.java.proxytest.InvokeMethodClass
进入invoke方法!
invoke执行结束

1.2 示例2--代理接口实现类(Spring中AOP实现之一)

TestInterface.java
public interface TestInterface {
public void saySomething(String thing);
}
TestInterfaceImpl.java
public class TestInterfaceImpl implements TestInterface
{
public void saySomething(String thing) {
System.out.println("接口实现类的方法:"+thing);
}
}
InvokeMethodClass.java
public class InvokeMethodClass implements InvocationHandler { //需要代理的实现类
private Object impl; //生成代理类
public Object bind(Object impl) {
this.impl = impl;
return (TestInterface) Proxy.newProxyInstance(TestInterface.class.getClassLoader(), impl.getClass().getInterfaces(), this);
} //方法调用时触发的方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入invoke方法!");
method.invoke(impl, "zzzzzz");
System.out.println("invoke执行结束");
return null;
} public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
InvokeMethodClass invokeMethodClass = new InvokeMethodClass(); TestInterface tt = (TestInterface) invokeMethodClass.bind(new TestInterfaceImpl());
System.out.println("代理类的class:" + tt.getClass().getName()); tt.saySomething("sssssss");
}
}

执行结果:java -cp G:\practice\idea-new\ideaMaven\target\classes test.java.proxytest.InvokeMethodClass

代理类的class:com.sun.proxy.$Proxy0
进入invoke方法!
接口实现类的方法:zzzzzz
invoke执行结束

2. Proxy.newProxyInstance源码分析

Proxy.newProxyInstance() -->  Class<?> cl = getProxyClass0(loader, intfs);
--> proxyClassCache.get(); //proxyClassCache来自何处
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
WeakCache(BiFunction<K, P, ?> subKeyFactory,
BiFunction<K, P, V> valueFactory) {
this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
this.valueFactory = Objects.requireNonNull(valueFactory);
}
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
--> ProxyClassFactory.apply(); //生产
--> byte[] proxyClassFile = ProxyGenerator.generateProxyClass( //生成classFile
proxyName, interfaces, accessFlags);
--> if(saveGeneratedFiles) //是否保存生成的class文件,前面设置的系统参数及在此处
saveGeneratedFiles = ((Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"))).booleanValue();

JDK动态代理详解-依赖接口的更多相关文章

  1. SpringBoot27 JDK动态代理详解、获取指定的类类型、动态注册Bean、接口调用框架

    1 JDK动态代理详解 静态代理.JDK动态代理.Cglib动态代理的简单实现方式和区别请参见我的另外一篇博文. 1.1 JDK代理的基本步骤 >通过实现InvocationHandler接口来 ...

  2. JDK动态代理详解

    JDK动态代理是代理模式的一种,且只能代理接口.spring也有动态代理,称为CGLib,现在主要来看一下JDK动态代理是如何实现的? 一.介绍 JDK动态代理是有JDK提供的工具类Proxy实现的, ...

  3. 转:JDK动态代理为什么必须用接口以及与CGLIB的对比

    参考链接: JDK动态代理为什么必须用接口以及与CGLIB的对比 文章中提到:试验了JDK动态代理与CGLIB动态代理.从Spring的AOP框架介绍中得知对于使用接口的类,Spring使用JDK动态 ...

  4. JDK、CGlib动态代理详解

    Java动态代理之JDK实现和CGlib实现(简单易懂)      一 JDK和CGLIB动态代理原理 1.JDK动态代理 利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生 ...

  5. 基于SpringBoot实现AOP+jdk/CGlib动态代理详解

    动态代理是一种设计模式.在Spring中,有俩种方式可以实现动态代理--JDK动态代理和CGLIB动态代理. JDK动态代理 首先定义一个人的接口: public interface Person { ...

  6. JDK动态代理、CGLIB动态代理详解

    Spring的AOP其就是通过动态代理的机制实现的,所以理解动态代理尤其重要. 动态代理比静态代理的好处: 1.一个动态代理类可以实现多个业务接口.静态代理的一个代理类只能对一个业务接口的实现类进行包 ...

  7. 【spring基础】AOP概念与动态代理详解

    一.代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

  8. JDK动态代理为什么必须针对接口

    查看jdk的动态代理源码发现: 动态代理实际上是程序在运行中,根据被代理的接口来动态生成代理类的class文件,并加载class文件运行的过程,通过反编译被生成的$Proxy0.class文件发现: ...

  9. cgkib动态代理详解-不依赖接口,速度快

    1. cglib原理-不依赖接口,速度快 使用ASM字节框架动态生成要代理类的子类,子类重写final以外的方法,织入横切逻辑 2. 示例-实现MethodInterceptor Test.java ...

随机推荐

  1. 伪分布模式 hive查询

    [root@node1 ~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian ...

  2. 【256】◀▶IEW-答案

    附答案 Unit I Fast food Model Answers: Model 1 The pie chart shows the fast foods that teenagers prefer ...

  3. 10个C语言经典

    1.计算Fibonacci数列Fibonacci数列又称斐波那契数列,又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.C语言实现的代码如下: /* t3ing Fibonac ...

  4. “box-shadow”属性(转)

    “box-shadow”属性 box-shadow属性是一个CSS3属性,允许我们在几乎任何元素上来创建阴影效果,类似于在设计软件中的”drop shadow”.这些阴影效果允许我们在原本平面的.二维 ...

  5. JavaScript学习系列7 -- JavaScript中的运算符

    今天,我们来说一说JavaScript中的运算符,首先我们来讲一讲 一元运算符 JavaScript中的一元运算符有以下几种 1. delete delete 运算符主要用于删除对以前定义的对象属性或 ...

  6. PHP7中Protobuf的安装使用

    PHP7中Protobuf的安装使用 写这篇文章的缘由是最近在关注RPC框架序列化的一些原理.但是在安装Protobuf的时候,发现网上的教程都太老了,加上目前Protobuf官方已经支持PHP了,不 ...

  7. [翻译]pytest测试框架(二):使用

    此文已由作者吴琪惠授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 调用pytest 调用命令: python -m pytest [...] 上面的命令相当于在命令行直接调用 ...

  8. iscsi使用教程(下)

    动态创建目标 安装iscsi服务端 # yum install -y scsi-target-utils.x86_64 修改配置文件 # mkdir -p ~/volumes # sed -i '$ ...

  9. Java面向对象的三大特性 继承

    继承是类与类的一种关系,是“is a"关系  子类拥有父类的属性和方法,private除外 class 子类 extends 父类   方法的重写 调用方法时会优先调用子类的方法 重写时,返 ...

  10. SAS笔记(3) LAG和DIFF函数

    在实际的应用中,我们会想查看当前观测的上一个观测值,在上一篇博客中我们使用了RETAIN语句来记录上一条观测,其实SAS还提供了一个很好用的函数LAG.当我们使用函数时,一定要明确该函数的返回值是什么 ...