一、什么是反射机制?

  反射的官方定义是这样的:在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息及动态调用类对象方法的功能称为java的反射机制。  

  讲的通俗一点的话就是,对于jvm来说,.java文件必须要先编译为.class文件才能够被jvm执行,所以在编译为.class文件的过程中,对象的类型都会被指定好,比如说 User user。那么如果说我想在代码运行的过程中获取到对象的类型呢?或者说程序在运行过程中如何载入一个特定的类呢?这就涉及到了java的反射机制了,反射提供了一套能够让我们在代码运行时也能获取到类型属性的方法。

二、反射的使用

  jdk提供了三种方式获取一个对象的Class,就User user来说

  1.user.getClass(),这个是Object类里面的方法

  2.User.Class属性,任何的数据类型,基本数据类型或者抽象数据类型,都可以通过这种方式获取类

  3.Class.forName(""),Class类提供了这样一个方法,让我们通过类名来获取到对象类

  这三种方法用的最多的就是第三种,那么获取到类之后,Class类提供了很多获取类属性,方法,构造方法的api。

  1.获取所有的属性

  1. //获取整个类
  2. Class c = Class.forName("java.lang.Integer");
  3. //获取所有的属性?
  4. Field[] fs = c.getDeclaredFields();
  5.  
  6. //定义可变长的字符串,用来存储属性
  7. StringBuffer sb = new StringBuffer();
  8. //通过追加的方法,将每个属性拼接到此字符串中
  9. //最外边的public定义
  10. sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");
  11. //里边的每一个属性
  12. for(Field field:fs){
  13. sb.append("\t");//空格
  14. sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
  15. sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字
  16. sb.append(field.getName()+";\n");//属性的名字+回车
  17. }
  18.  
  19. sb.append("}");
  20.  
  21. System.out.println(sb);

  2.获取特定的属性

  1. //获取类
  2. Class c = Class.forName("User");
  3. //获取id属性
  4. Field idF = c.getDeclaredField("id");
  5. //实例化这个类赋给o
  6. Object o = c.newInstance();
  7. //打破封装
  8. idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
  9. //给o对象的id属性赋值"110"
  10. idF.set(o, "110"); //set
  11. //get
  12. System.out.println(idF.get(o));

  3.获取方法

  1. getDeclaredMethods() 获取所有的方法
  2.  
  3. getReturnType() 获得方法的放回类型
  4.  
  5. getParameterTypes() 获得方法的传入参数类型
  6.  
  7. getDeclaredMethod("方法名",参数类型.class,……) 获得特定的方法
  8.  
  9. getDeclaredConstructors() 获取所有的构造方法
  10.  
  11. getDeclaredConstructor(参数类型.class,……) 获取特定的构造方法
  12.  
  13. getSuperclass() 获取某类的父类
  14.  
  15. getInterfaces() 获取某类实现的接口

三、反射的作用和动态代理 

  反射作用总结就是:1.动态地创建类的实例,将类绑定到现有的对象中,或从现有的对象中获取类型。2.应用程序需要在运行时从某个特定的程序集中载入一个特定的类。

那么什么是动态代理呢?先给出百度的答案:动态代理,就是根据对象在内存中加载的Class类创建运行时类对象,从而调用代理类方法和属性。

  代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。而代理模式又分为静态代理和动态代理,先说静态代理。

  静态代理通俗点将就是自己手写一个代理类,而动态代理则不用我们手写,而是依赖于java反射机制,下面以一个demo举例。

  demo结构如图:

  

  Subject是一个普通接口,里面有个抽象的doSomething()的方法,而SubjectImpl.java是它的普通的实现类,如下所示。

    

  

  而HandProxy.java就是SubjectImpl的静态代理类,代替了SubjectImpl完成doSomething的工作,如下所示

  

  这样做的好处是对于doSomething方法来说,我用静态代理类来实现,可以任意的在其中插入我需要额外做的事情,比如说记录日志。

  那么AutoProxy.java就是动态代理类了,具体如下所示。

  

  这里面首先想要做到动态代理,必须先实现这个InvocationHandler接口,然后我们主要看bind方法,参数tar是一个Object类型的对象,也就是需要被代理的对象SubjectImpl,

方法里面有一个Proxy类,这个Proxy类提供了很多方法,这里我们用的是newProxyInstance方法,它有三个参数,第一个是被代理类的类构造器,第二个指的是被代理类的接口,也就是Subject接口,第三个是实现这个代理的类,这里就是本类。具体的来说,这个方法执行了下面三步:

1.生成一个实现了参数interfaces里所有接口且继承了Proxy的代理类的字节码,然后用参数里的classLoader加载这个代理类。

2.使用代理类父类的构造函数 Proxy(InvocationHandler h)来创造一个代理类的实例,将我们自定义的InvocationHandler的子类传入。

3.返回这个代理类实例,因为我们构造的代理类实现了interfaces(也就是我们程序中传入的subject.getClass().getInterfaces())里的所有接口,因此返回的代理类可以强转成Subject类型来调用接口中定义的方法。

  而在调用每个代理类每个方法的时候,都用反射去调h的invoke方法(也就是我们自定义的InvocationHandler的子类中重写的invoke方法),用参数传递了代理类实例、接口方法、调用参数列表,这样我们在重写的invoke方法中就可以实现对所有方法的统一包装了。

  总结一下,静态代理的优点是清晰易懂,但是如果说业务代码很多,那么在代理类里面必须全部重新调用一遍,很麻烦。而动态代理,利用java反射机制,动态的生成了一个代理类,直接调用代理方法即可。

四、总结

  反射这一块是博主最近在看框架源码的时候总是遇到这类问题所以刻意去整理了一下,里面有些东西其实我也研究的不是很深刻,动态代理这边的源码还有待深入挖掘,若有大神发现写的不对的地方,还请多多指教,谢谢。

java反射与动态代理的理解的更多相关文章

  1. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

  2. Java反射和动态代理

    Java反射 反射机制 RTTI 编译器在编译时打开和检查*.class文件 反射机制 运行时打开和检查*.class文件 Java反射常见的方法 java反射的应用 setAccessible(bo ...

  3. Java反射机制动态代理

    1.什么事反射机制动态代理 在一段代码的前后动态执行其他操作,比如有一个方法是往数据库添加一个记录,我们可以通过动态代理,在操作数据库方法的前和后添加代码执行打开数据库连接和关闭数据库连接. 2.演示 ...

  4. java反射和动态代理实现与原理详细分析

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...

  5. java反射实现动态代理

    参考:http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html http://my.oschina.net/lyp3314/b ...

  6. 深入分析Java反射(四)-动态代理

    动态代理的简介 Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分 ...

  7. Java反射与动态代理

    Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制.java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的 ...

  8. Java反射 - 3(动态代理)

    动态代理是对包装模式的升级,可以动态的传入需要代理的对象实现代理 准备如下 1. 被代理类的接口 2.被代理类 3.处理器:InvocationHandler 4.代理调用:Proxy.newInst ...

  9. Java 反射之动态代理

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt205 利用Java反射机制你可以在运行期动态的创建接口的实现.java.la ...

随机推荐

  1. 单片机之PID算法

    说到PID算法,想必大部人并不陌生,PID算法在很多方面都有重要应用,比如电机的速度控制,恒温槽的温度控制,四轴飞行器的平衡控制等等,作为闭环控制系统中的一种重要算法,其优点和可实现性都成为人们的首选 ...

  2. pyinstaller打包程序 带图片

    首选说一下,这种打包方式只能在本电脑上使用运行正常 准备:.py文件:你的程序 gif文件:你要用的图片 第一步: 在上面文件所在目录打开cmd 输入 pyi-makespec FP.py 会生成一个 ...

  3. RSA 算法

    RSA 算法  from http://www.matrix67.com/blog/archives/5100 所有工作都准备就绪,下面我们可以开始描述 RSA 算法了. 首先,找两个质数,比如说 1 ...

  4. 从navicat中导入sql文件过大:Got a packet bigger than 'max_allowed_packet' bytes

    失败背景:刚才通过navicat向本地mysql数据库中导入sql文件.第一个sql文件(多个表)大小为967M,导入成功: 第二个sql(单个表)大小为50.1M,导入失败. 1.在navicat中 ...

  5. Linux pwn入门教程(3)——ROP技术

    作者:Tangerine@SAINTSEC 原文来自:https://bbs.ichunqiu.com/thread-42530-1-1.html 0×00 背景 在上一篇教程的<shellco ...

  6. Java学习笔记36(File类)

    File类可以对操作系统中的文件进行操作: File类的静态成员变量: package demo; import java.io.File; public class FileDemo { publi ...

  7. Docker 与 虚拟机比较

    1, 更高效的利用系统资源2,更快速的启动时间3,一致的运行环境4,持续交付(Continuous Integration)和部署(Continuous Delivery) 5, 更轻松的迁移 6,更 ...

  8. Spring Boot Debug调试

    在使用spring-boot:run进行启动的时候,如果设置的断点进不去,要进行以下的设置. 1.添加jvm参数配置 在spring-boot的maven插件加上jvmArguments配置. < ...

  9. LeetCode--No.003 Longest Substring Without Repeating Characters

    Longest Substring Without Repeating Characters Total Accepted: 167158 Total Submissions: 735821 Diff ...

  10. 纯JavaScript实现俄罗斯方块(详细注释,ES6)

    借鉴了慕课网的课程<基于websocket的火拼俄罗斯(单机版)>虽然改动比较多,但是还是核心部分没有改,加了一些不怎么好听的声音,和看起来并不好看的界面. CSS部分基本是瞎写的,因为对 ...