JDK动态代理详解-依赖接口
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动态代理详解-依赖接口的更多相关文章
- SpringBoot27 JDK动态代理详解、获取指定的类类型、动态注册Bean、接口调用框架
1 JDK动态代理详解 静态代理.JDK动态代理.Cglib动态代理的简单实现方式和区别请参见我的另外一篇博文. 1.1 JDK代理的基本步骤 >通过实现InvocationHandler接口来 ...
- JDK动态代理详解
JDK动态代理是代理模式的一种,且只能代理接口.spring也有动态代理,称为CGLib,现在主要来看一下JDK动态代理是如何实现的? 一.介绍 JDK动态代理是有JDK提供的工具类Proxy实现的, ...
- 转:JDK动态代理为什么必须用接口以及与CGLIB的对比
参考链接: JDK动态代理为什么必须用接口以及与CGLIB的对比 文章中提到:试验了JDK动态代理与CGLIB动态代理.从Spring的AOP框架介绍中得知对于使用接口的类,Spring使用JDK动态 ...
- JDK、CGlib动态代理详解
Java动态代理之JDK实现和CGlib实现(简单易懂) 一 JDK和CGLIB动态代理原理 1.JDK动态代理 利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生 ...
- 基于SpringBoot实现AOP+jdk/CGlib动态代理详解
动态代理是一种设计模式.在Spring中,有俩种方式可以实现动态代理--JDK动态代理和CGLIB动态代理. JDK动态代理 首先定义一个人的接口: public interface Person { ...
- JDK动态代理、CGLIB动态代理详解
Spring的AOP其就是通过动态代理的机制实现的,所以理解动态代理尤其重要. 动态代理比静态代理的好处: 1.一个动态代理类可以实现多个业务接口.静态代理的一个代理类只能对一个业务接口的实现类进行包 ...
- 【spring基础】AOP概念与动态代理详解
一.代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...
- JDK动态代理为什么必须针对接口
查看jdk的动态代理源码发现: 动态代理实际上是程序在运行中,根据被代理的接口来动态生成代理类的class文件,并加载class文件运行的过程,通过反编译被生成的$Proxy0.class文件发现: ...
- cgkib动态代理详解-不依赖接口,速度快
1. cglib原理-不依赖接口,速度快 使用ASM字节框架动态生成要代理类的子类,子类重写final以外的方法,织入横切逻辑 2. 示例-实现MethodInterceptor Test.java ...
随机推荐
- Python:easygui的安装、导入、使用、设置
转于:https://blog.csdn.net/sinat_37390744/article/details/55211652 博主:钏的博客 一.下载安装 1)下载0.96的easygui.htt ...
- java类加载器-----用户自定义类加载器实现
java类加载器主要分为如下几种: jvm提供的类加载器 根类加载器:底层实现,主要加载java核心类库(如:java.lang.*) 扩展类加载器:使用java代码实现,主要加载如:jre/lib/ ...
- Android精品源码分享第四波袭来,免费下载!
今天又汇总了几个优质的源码分享出来给大家!希望可以帮到需要的朋友~1.Android实现-带动画的饼图控件 分享的是Android技术相关的源码内容,希望对大家的Android学习有帮助.带动画的饼图 ...
- linux日常管理-rsync常用选项详解
-av 同步目录 写法 123/ /tmp/333/ 意思是把123下的文件同步到/tmp/333/下 结尾不加/ 只同步目录 两个目录一样的. //////////////////////// ...
- NASA的CTO——开源软件使我们诚实
Chris C.Kemp,谷歌设置新职位CTO让他领导 原文: NASA's CTO: Open source software keeps us honest 作者: Shawn Freeman 译 ...
- CSS多列布局Multi-column、伸缩布局Flexbox、网格布局Grid详解
新css属性为我们提供了更加便捷的网页布局方式.来自微软的thomas lewis将带你认识去Grid Alignment,Flexibox Box以及Multi-column Layout这三大领域 ...
- (转载)Windows无法安装到GPT分区形式磁盘解决办法
之前使用的是windows7 + ubuntu18.04双系统,硬盘分区采用的是GPT格式.重装windows系统时,提示“windows无法安装到这个磁盘.选中的磁盘采用GPT分区形式”,导致安装失 ...
- 使用 Node.js 实现简单的 Webhook
距离 Node.js 这个东西出来已经过了好久了,感觉现在的前端如果不会点 Node.js 就有点太落后于时代啦.我接触它是从去年暑假开始的,当时在写一个比较神奇的东西,就顺便接触了一下.虽然网传 n ...
- 手机连接fiddler后,浏览器无法打开网页或者fiddler抓取不到手机应用相关数据的情况
关于手机如何连接fiddler,网上有很多教程,我暂时就不写了 今天在使用fiddler的过程中,发现fiddler突然无法抓取移动端应用的数据包,再三确认连接无误.因此就开始了解决之旅 起因是安卓手 ...
- IOHelper(自制常用的输入输出的帮助类)
常用的读写文件,和地址转换(win和linux均支持),操作文件再也不是拼接那么的low了 using System; using System.Diagnostics; using System.I ...