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. Guice 学习

    Guice: 是一个轻量级的DI框架. 不需要繁琐的配置,只需要定义一个Module来表述接口和实现类,以及父类和子类之间的关联关系的绑定,如下是一个例子. http://blog.csdn.net/ ...

  2. WCF服务用户名密码访问

    有2种方式, 第一直接在程序中指定用户名密码,配置调用 private void BtnSearch_Click(object sender, EventArgs e) { try { var cli ...

  3. GIF助手帮助说明

    生成的文件位置? 生成的GIF等文件存储在 /sdcard/gifdir/ 目录下. 为什么分享到微信.Twitter等平台失败? 微信.Twitter等平台对GIF文件大小有限制,微信限制为1MB, ...

  4. SpringBoot04 SpringBoot 和 MyBatis 整合

    1 所需的jar包 mysql驱动包:mysql-connector-java 数据库链接池:druid mybatis对应jar包:mybatis-spring-boot-starter 分页查询对 ...

  5. 转——AHRS(航姿参考系统)和IMU(惯性测量单元)的区别

    AHRS(航姿参考系统)和IMU(惯性测量单元)的区别  [测试测量] 发布时间:2010-05-09 16:52:09  http://bbs.ednchina.com/BLOG_ARTICLE_1 ...

  6. ps&CPU

    #include <pthread.h> void f();int main() {        f();        return 0;} void f() {        int ...

  7. codeforces 367B

    题目代码到是不难但是很难想通题目的解决方法. #include<iostream> using namespace std; ]; int main() { int n,m; while( ...

  8. jeecms v8 网站访问量配置

    <script src="${resSys}/jquery.js" type="text/javascript"></script> & ...

  9. C++基础之类和对象二

    (1)指向类的成员的指针分为指向数据成员的指针和指向成员函数的指针两种.一个类的对象用运算符“.*”来操作指向该类成员的指针,而一个指向类的对象的指针用运算符“->”来操作指向该类成员的指针.( ...

  10. 使用 PHPMailer 发送邮件出现诡异bug,间歇性发送失败

    场景 使用PHPMailer的SMTP发送邮件,用的是腾讯企业邮箱 smtp.exmail.qq.com 在邮箱设置里看到配置smtp方法 问题描述 本地windows开发环境发送邮件100%成功 远 ...