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. Hdu 4762 网络赛 高精度大数模板+概率

    注意题目中的这句话he put the strawberries on the cake randomly one by one,第一次选择草莓其实有N个可能,以某一个草莓为开头,然后顺序的随机摆放, ...

  2. 给JZ2440开发板重新分区

    转自:http://mp.weixin.qq.com/s?__biz=MzAxNTAyOTczMw==&mid=2649328035&idx=1&sn=7d3935cc05d3 ...

  3. altium designer 中的top/bottom solder和top/bottom paste mask

    转载请注明出处:http://blog.csdn.net/qq_26093511/article/details/51751936 1.top solder为助焊层,说白一点就是说,有这个层的地方就没 ...

  4. ng2-升级脚手架到最新版本

    //先卸载,后安装 npm uninstall -g @angular/cli npm cache clean npm install -g @angular/cli@latest

  5. JavaScript原型模式(prototype)

    1.原型是一个对象,其他对象可以通过它实现属性的继承所有对象在默认的情况下都有一个原型,因为原型的本身也是对象,所以一个类的真正原型是被类的内部[prototype]属性所指出.每个函数都有一个属性叫 ...

  6. 1.Apache+Tomcat负载均衡+集群配置

    1.本文Apache+Tomcat集群配置 基于最新的Apache和Tomcat,具体是2011年4月20日最新的Tomcat和Apache集群和负载均衡配置. 准备环境 Apache Apache是 ...

  7. 5.JasperReports学习笔记5-其它数据生成动态的报表(WEB)

    转自:http://www.blogjava.net/vjame/archive/2013/10/12/404908.html 一.空数据(Empty Datasources) 就是说JRXML文件里 ...

  8. Android精品源码分享第四波袭来,免费下载!

    今天又汇总了几个优质的源码分享出来给大家!希望可以帮到需要的朋友~1.Android实现-带动画的饼图控件 分享的是Android技术相关的源码内容,希望对大家的Android学习有帮助.带动画的饼图 ...

  9. 利用httpclient和mysql模拟搜索引擎

    数据抓取模块 package crowling1; import java.sql.CallableStatement; import java.sql.Connection; import java ...

  10. c/c++转义字符大全【转自互联网】

    将转义字符收集如下:转义字符 意义 ASCII码值(十进制) \a 响铃(BEL) 007 \b 退格(BS) 008 \f 换页(FF) 012 \n 换行(LF) 010 \r 回车(CR) 01 ...