精华内容
下载资源
问答
  • 声明:非常感谢yy629 提供的帮助。原文:java的动态代理...如何导出动态代理生成的类的字节码文件(*.class)呢?   只需要在应用中添加下面一段代码:   Field field = System.class.getDeclaredField("p...

    声明:非常感谢yy629 提供的帮助。原文:java的动态代理生成了什么?

     

    要查看java动态代理生成的源文件,必须先导出字节码文件然后通过反编译(如jad工具)生成源文件。

     

    如何导出动态代理生成的类的字节码文件(*.class)呢?

     

    只需要在应用中添加下面一段代码:

     

    Field field = System.class.getDeclaredField("props");  
    field.setAccessible(true);  
    Properties props = (Properties) field.get(null);  
    props.put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");  

     

    当运行该段代码的程序,会在使用了动态代理的类包中生成对应的动态代理类的字节码。

     

    结论:动态代理类会自动地添加上toString,hashCode,equals方法,而且这三个方法都会调用InvocationHandler中的invoke方法。这就是为什么在生成的代理类中调用toString,hashCode,equals都会执行invoke的原因。

    展开全文
  • 查看JDK动态代理生成的类的内容

    千次阅读 2017-09-10 00:37:42
    首先我们先定义一个接口: public interface PersonInter {...}接着就是我们想的要生成的JDK代理类源码的代码: public class JdkProxySourceClass { public static void writeClassToDisk(String path){ byte[] c

    首先我们先定义一个接口:

    public interface PersonInter {
    
        String test(String str);
    }
    接着就是我们想的要生成的JDK代理类源码的代码:

    public class JdkProxySourceClass {
    
    	public static void writeClassToDisk(String path){
    
    		byte[] classFile = ProxyGenerator.generateProxyClass("$proxy4", new Class[]{PersonInter.class});
    		FileOutputStream fos = null;
    		try {
    			fos = new FileOutputStream(path);
    			fos.write(classFile);
    			fos.flush();
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}finally{
    			if(fos != null){
    				try {
    					fos.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    
        @Test  
        public void testGenerateProxyClass() {  
        	JdkProxySourceClass.writeClassToDisk("D:/$Proxy4.class");  
        }  
    }
    重要的就是这一句话:byte[] classFile = ProxyGenerator.generateProxyClass("$proxy4", new Class[]{PersonInter.class});

    OK接下来我们用反编译工具看一下生成的代理类源码:

    import com.zkn.newlearn.gof.proxyhandler.PersonInter;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    public final class Proxy4 extends Proxy
      implements PersonInter
    {
      private static Method m1;
      private static Method m2;
      private static Method m3;
      private static Method m0;
    
      public Proxy4(InvocationHandler paramInvocationHandler)
        throws 
      {
        super(paramInvocationHandler);
      }
    
      public final boolean equals(Object paramObject)
        throws 
      {
        try
        {
          return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
    
      public final String toString()
        throws 
      {
        try
        {
          return ((String)this.h.invoke(this, m2, null));
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
    
      public final String test(String paramString)
        throws 
      {
        try
        {
          return ((String)this.h.invoke(this, m3, new Object[] { paramString }));
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
    
      public final int hashCode()
        throws 
      {
        try
        {
          return ((Integer)this.h.invoke(this, m0, null)).intValue();
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
    
      static
      {
        try
        {
          m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
          m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
          m3 = Class.forName("com.zkn.newlearn.gof.proxyhandler.PersonInter").getMethod("test", new Class[] { Class.forName("java.lang.String") });
          m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
          return;
        }
        catch (NoSuchMethodException localNoSuchMethodException)
        {
          throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException localClassNotFoundException)
        {
          throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
        }
      }
    }


    从反编译出来的源码中我们可以看到在静态代码块中得到了equals、toString、hashCode和PersonInter接口中test方法的Method对象。当我们调用PersonInter中的test方法的时候:

      public final String test(String paramString)
        throws 
      {
        try
        {
          return ((String)this.h.invoke(this, m3, new Object[] { paramString }));
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }

    其实是调用了InvocationHandler中的invoke方法,并传入了之前获取到的对应的Method和参数。在这里也简单的说一下为什么JDK的动态代理只能代理接口不能代理类,请注意看我们所得到的代理类的源码,注意看这一句:public final class Proxy4 extends Proxy implements PersonInter。生成的代理类默认继承了Proxy这个类,而java中又是单继承的,所以这里只能代理接口,不能代理类了。就像枚举类,不能继承别的枚举类一样。

    展开全文
  • 如果我们要研究JDK动态生成的代理类,此时则需要将内存中的代理类作为.class文件保存到磁盘,再通过Java反编译工具查看其源码;这个过程可以通过设置系统属性让JRE来自动完成或者通过IO流写入到磁盘


    如果我们要研究JDK动态生成的代理类,此时则需要将内存中的代理类作为.class文件保存到磁盘,再通过Java反编译工具查看其源码

    (方式一)设置系统属性

    在调用newProxyInstance之前将sun.misc.ProxyGenerator.saveGeneratedFiles系统属性设置为true,生成的代理类将被自动写入磁盘;class文件在 \Workspaces\项目名称\com\sun\proxy 路径下

    	public Object getProxy() {
    		System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); //设置系统属性
    		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
    				target.getClass().getInterfaces(), this); 
    	}
    

    (方式二)保存ProxyGenerator生成的字节流数组

    直接通过ProxyGenerator的静态方法generateProxyClass(JDK源码中Proxy.newProxyInstance\color{blue}{Proxy.newProxyInstance}实际就是调用ProxyGenerator.generateProxyClass\color{blue}{ProxyGenerator.generateProxyClass}方法生成的class对应的字节数组)生成代理类的字节数组表示,再通过IO流写到磁盘

    代理类的class文件在 \Workspaces\项目名称\bin\目标类所在的包 路径下

    	public Object getProxy() {		
    		saveClassFile(target.getClass(),"AtmProxy");//调用保存为class字节码文件
    		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
    				target.getClass().getInterfaces(), this); 
    	}
    
    	/**
    	 * 保存class文件
    	 * @param clazz	      class对象
    	 * @param proxyName	  代理类的名字,可随意指定	
    	 * @param classBytes
    	 */
    	public void saveClassFile(Class clazz,String proxyName) {
    	    //生成class的字节数组,此处生成的class与proxy.newProxyInstance中生成的class除了代理类的名字不同,其它内容完全一致
    		byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, clazz.getInterfaces());
    		String path = clazz.getResource(".").getPath();
    		FileOutputStream fos = null;
    		try {
    			fos = new FileOutputStream(path + proxyName + ".class");
    			fos.write(classFile);//保存到磁盘
    			fos.flush();
    		}catch(Exception e) {
    			e.printStackTrace();
    		}finally {
    			try {
    				fos.close();
    			}catch(IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    

    类导入问题处理

    如果出现Access restriction: The type ‘ProxyGenerator’ is not API (restriction on required library ‘C:\Program Files\Java\jre1.8.0_72\lib\rt.jar’)问题
    在这里插入图片描述

    import sun.misc.ProxyGenerator;
    
    语句无效,会导致 ProxyGenerator  cannot be resolved 错误;
    

    原因是 ProxyGenerator\color{blue}{ProxyGenerator} 不属于JDK API的内容,默认不给导入

    \color{blue}解决方法
    1.选中工程右键 -> Properties
    2.Java build path -> libraries -> JRE System Library
    3.点击右侧靠下方Edit
    4.选择默认的JRE环境,Workspace default JRE; 或者选择Alternate JRE ->Installed JREs 导入JRE的目录环境

    JDK动态代理完整代码

    JDK动态代理完整代码请参考专题内容:https://blog.csdn.net/write6/article/details/89719646#font_size4JDKfont_48

    展开全文
  • 启动时加: -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true

    启动时加:

    -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true

     

    展开全文
  • 阅读过上一章童鞋可以发现,mybatis只需要配置上@MapperScan注解就可以将扫描包路径下mapper实例化,底层使用是jdk的动态代理, 下面我们模仿一个简单@MyMapperScan实现类似简单功能 首先我们模仿一个...
  • 将JDK动态代理生成的类保存为 .class文件System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");无效,没有看到相应的字节码文件,这是因为System.setProperty("sun.misc.ProxyGenerator....
  • 在这里也简单的说一下为什么JDK的动态代理只能代理接口不能代理,请注意看我们所得到的代理的源码,注意看这一句:public final class Proxy4 extends Proxy implements PersonInter。生成的代理默认继承了...
  • jdk8及之前:System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); jdk8之后:System.setProperty("jdk.proxy.... 如果有异常情况:可根据以下方式直接在jdk中搜索ProxyGenerator确定!!!
  • 动态代理及其生成的代理,可以反编译查看其的结构。
  • 保存动态代理生成的代理.class import java.util.Properties; /** * Main * @author zjl * @date 2019/12/12 */ public class Main { public static void main(String[] args) { // 保存操作 Properti.....
  • 使用mybaitis的mapper接口执行sql语句时,我们拿到其实是接口实现的代理,这个代理是由mybatis使用动态代理生成的接口实现。 mybatis通过配置 MapperFactoryBean来生成Mapper接口的代理。如: <pr
  • 一、生成动态代理类$Proxy0.class /** * 被代理 */ public interface Product { void method(); } 二、还原我们代理 public static void createProxyClassFile(){ byte[] data = ...
  • 1 动态代理动态代理的实现方式常用的有两种:反射实现:基于反射实现,目标对象必须要有接口。生成的代理是接口的一个实现Cglib实现:基于字节码实现,效率稍低,但目标对象不需要有接口。生成的代理是目标...
  • Java中动态代理技术生成的类与原始类的区别 用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑.  平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道...
  • JDK动态代理代理类的生成与缓存一、缓存相关的类及主要结构代理类的生成与缓存主要在java.lang.reflect.WeakCache&lt;K, P, V&gt;这个类中完成,此类用于代理类缓存的主要结构如下// 用了Reference记录引用...
  • cglib 生成动态代理类的机制

    千次阅读 2016-11-24 21:50:53
    ... JDK中提供的生成动态代理类的机制有个鲜明的特点是: 某个必须有实现的接口,而生成的代理也只能代理某个接口定义的方法,比如:如果上面例子的ElectricCar实现了继承自两个接
  • 1.为什么会有这样想法去生成接口实现 在学习mybatis过程中...思考:由于我们没有写该接口实现,mybatis返回对象肯定不是简单的动态代理 但是我们打印其返回对象class发现 class com.sun.proxy.$...
  • Java获取动态生成的代理类

    千次阅读 2019-02-26 17:15:26
    Java获取动态生成的代理 以下以获取mybatis动态代理为例子 获取java进程的id 使用cmd命令,获取java运行id,可见端口号为11944 netstat -aon|findstr "端口号" 查看JVM运行数据 使用cmd命令,开启...
  • 1、定义一个接口 ...2、定义实现 public class RealHandlerInterface implements IHandlerInterface { @Override public void test() { ServiLogger.log("RealHandlerInterface: test");
  • 使用wsdl生成的代理类或者添加web引用方式生成的WebReference文件夹,都得在对方WebService发布出来之后,才能产生对应的代理类。如果之后对方WebService中添加了新点方法,我们要调用的话,必须重新生成已经存在的...
  • Java动态代理,顾名思义,动态的生成代理对象。其实难点就在这里—动态。到底怎么动态生成。代理解决问题就是增强。其实,实现代理方式很多种,比如继承,子类对一个增强,我们可以认为子类就是一个代理,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,599
精华内容 2,239
关键字:

动态代理生成的类