java反射与动态代理的理解
一、什么是反射机制?
反射的官方定义是这样的:在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息及动态调用类对象方法的功能称为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.获取所有的属性
//获取整个类
Class c = Class.forName("java.lang.Integer");
//获取所有的属性?
Field[] fs = c.getDeclaredFields(); //定义可变长的字符串,用来存储属性
StringBuffer sb = new StringBuffer();
//通过追加的方法,将每个属性拼接到此字符串中
//最外边的public定义
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");
//里边的每一个属性
for(Field field:fs){
sb.append("\t");//空格
sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字
sb.append(field.getName()+";\n");//属性的名字+回车
} sb.append("}"); System.out.println(sb);
2.获取特定的属性
//获取类
Class c = Class.forName("User");
//获取id属性
Field idF = c.getDeclaredField("id");
//实例化这个类赋给o
Object o = c.newInstance();
//打破封装
idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
//给o对象的id属性赋值"110"
idF.set(o, "110"); //set
//get
System.out.println(idF.get(o));
3.获取方法
getDeclaredMethods() 获取所有的方法
getReturnType() 获得方法的放回类型
getParameterTypes() 获得方法的传入参数类型
getDeclaredMethod("方法名",参数类型.class,……) 获得特定的方法
getDeclaredConstructors() 获取所有的构造方法
getDeclaredConstructor(参数类型.class,……) 获取特定的构造方法
getSuperclass() 获取某类的父类
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反射与动态代理的理解的更多相关文章
- Java 反射 设计模式 动态代理机制详解 [ 转载 ]
Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...
- Java反射和动态代理
Java反射 反射机制 RTTI 编译器在编译时打开和检查*.class文件 反射机制 运行时打开和检查*.class文件 Java反射常见的方法 java反射的应用 setAccessible(bo ...
- Java反射机制动态代理
1.什么事反射机制动态代理 在一段代码的前后动态执行其他操作,比如有一个方法是往数据库添加一个记录,我们可以通过动态代理,在操作数据库方法的前和后添加代码执行打开数据库连接和关闭数据库连接. 2.演示 ...
- java反射和动态代理实现与原理详细分析
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式 代理模式是常用的java设计模式, ...
- java反射实现动态代理
参考:http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html http://my.oschina.net/lyp3314/b ...
- 深入分析Java反射(四)-动态代理
动态代理的简介 Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分 ...
- Java反射与动态代理
Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制.java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的 ...
- Java反射 - 3(动态代理)
动态代理是对包装模式的升级,可以动态的传入需要代理的对象实现代理 准备如下 1. 被代理类的接口 2.被代理类 3.处理器:InvocationHandler 4.代理调用:Proxy.newInst ...
- Java 反射之动态代理
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt205 利用Java反射机制你可以在运行期动态的创建接口的实现.java.la ...
随机推荐
- httpd-vhosts.conf配置
<VirtualHost 127.0.0.1:80> ServerName zjm.appems.com DocumentRoot E:\qian\web <Directory &q ...
- centos7系统下,配置学校客户端网络记录
存在的情况 1.学校的网络客户端绑定了个人的电脑MAC地址.绑定了IP地址. 2.我有两台笔记本,一台用了4年多,想用这台(B)直接装centos7系统,然后新买的笔记本(A)做为经常用的,系统为wi ...
- 项目Alpha冲刺(团队2/10)
项目Alpha冲刺(团队2/10) 团队名称: 云打印 作业要求: 项目Alpha冲刺(团队) 作业目标: 完成项目Alpha版本 团队队员 队员学号 队员姓名 个人博客地址 备注 221600412 ...
- GC垃圾回收机制,iOS内存管理。
问题: MRC中通过调用静态方法创建的新对象,不再使用时需要对其发送release消息吗? 不需要,因为约定静态方法创建的对象会自动将其放入自动释放池,即已对其发送autorelease消息,因此不可 ...
- ACM知识点分类
(知识点分类.看完想(╯‵□′)╯︵┻━┻) orz...一点点来吧.简单标记一下. 蓝色,比较熟悉,能够做. 蓝绿色,一般熟悉,需要加强 红色,(比个辣鸡.jpg) (标记完突然想打人...) 第一 ...
- jmeter获取cookies信息(配置)
jmeter发送请求后,响应信息里获取不到cookies(实际上会返回一个cookies),解决方法: 在jmeter.properties里找到CookieManager.save.cookies, ...
- USB插入电脑的硬件检测和枚举流程
USB协议定义了设备的6种状态,仅在枚举过程种,设备就经历了4个状态的迁移:上电状态(Powered),默认状态(Default),地址状态(Address)和配置状态(Configured)(其他两 ...
- SQL分别求行、列的平均值
日常工作中,会需要用SQL求平均值,分别是求某一项的平均值或求某一个对象的平均值,放到表格就是求一行中的几个字段的平均值和求一列的平均值. 第一种:[列的平均值]AVG:这个函数相信大家都不陌生的,求 ...
- [视频]K8飞刀 HackIE\EXP测试\Post提交
[视频]K8飞刀 HackIE VS Firefox Hackbar插件功能对比 视频中可看到HackBar有缺陷导致Payload无法执行 链接:https://pan.baidu.com/s/15 ...
- jenkins配置邮件 -- com.sun.mail.smtp.SMTPSenderFailedException: 550 5.7.1 Client does not have permissions to send as this sender
jenkins配置邮件设置 发送邮件测试时,报错: com.sun.mail.smtp.SMTPSenderFailedException: Client does not have permissi ...