Java反射机制以及动态代理
Java反射机制以及动态代理
Java反射机制
含义与功能
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。
换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
Class类
认识Class类:
Class类是一个比较特殊的类,它是反射机制的基础 ,对于一个字节码文件.class,虽然表面上我们对该字节码文件一无所知,但该文件本身却记录了许多信息。Java在将.class字节码文件载入时,JVM将产生一个java.lang.Class对象代表该.class字节码文件,从该Class对象中可以获得类的许多基本信息,这就是反射机制。所以要想完成反射操作,就必须首先认识Class类。
在Java中程序获得Class对象有如下3种方式:
使用Class类的静态方法
forName(String className),其中参数className表示所需类的全名。例如:Class example = Class.forName("top.changtong1819.java.test")看着挺眼熟,这不就是学JDBC时连接数据库时的写法吗?
Class.forName(xxxx)用类名调用该类的class属性来获得该类对应的Class对象,即“类名.class”。
例如:
Class example = test.class用对象调用
getClass()方法来获得该类对应的Class对象,即“对象.getClass()”。例如:
Class example = new Test("haha").getClass()
通过类的class属性获得该类所对应的Class对象,会使代码更安全,程序性能更好,因此大部分情况下建议使用第二种方式。使用功能”.class”来创建Class对象的引用时,不会自动初始化该Class对象,使用forName()会自动初始化该Class对象。
创建实例对象:
创建运行时类的对象,使用newInstance(),实际上就是调用运行时指定类的无参构造方法。
public void test() throws Exception{
Class example =Class.forName("top.changtong1819.Person");
Person person = (Person)example.newInstance();
}
这里单单使用无参构造自然是不行的,满足不了实际使用需求,因此我们还需要想办法创建带参构造,这就是下面要讲的构造器的使用了。
类的反射
获取成员方法:一个成员方法就是一个Method对象
getMethods()返回该类继承以及自身声明的所有public的方法数组getDeclaredMethods()返回该类自身声明的所有public的方法数组,不包括继承而来
//用invoke(Object, Object...)可以调用该方法
//带参的public方法:第一个参数是方法名,后面的可变参数列表是参数类型的Class类型
Method test = example.getMethod("test",String.class);
//调用获得的方法,调用时候传递参数
test.invoke(person,"hehe");
获取成员变量:一个成员变量就是一个Fields对象
getFields()获取所有的public的成员变量信息,包括继承的。getDeclaredFields()获取该类自己声明的成员变量信息,public,private等
获取Java语言修饰符的int返回值:可调用Modifier.toString()获取修饰符的字符串形式:
getModifiers()以整数形式返回由此对象表示的字段的 Java 语言修饰符。
获取注释:
getAnnotations()返回此元素上存在的所有注释。getDeclaredAnnotations()返回直接存在于此元素上的所有注释。
获取构造函数:Constructor对象
getConstructors()返回所有public构造方法getDeclaredConstructors()返回类的所有构造方法
//Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。
Person person = (Person) constructor.newInstance("p", "person");
动态代理
动态代理是指通过代理类来调用它对象的方法,并且是在程序运行使其根据需要创建目标类型的代理对象。它只提供一个代理类,我们只需要在运行时候动态传递给需要他代理的对象就可以完成对不同接口的服务了。
在Java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。
InvocationHandler接口:
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy: 指代我们所代理的那个真实对象
method: 指代的是我们所要调用真实对象的某个方法的Method对象
args: 指代的是调用真实对象某个方法时接受的参数
Proxy类:
Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
动态代理示例:
//定义一个接口
public interface Person{
void say();
void eat();
}
//定义该接口的实现类
public class Man implements Person{
void say(){
System.out.println("多喝岩浆");
}
void eat(){
System.out.println("人在家中坐,狗粮天上来");
}
}
//定义一个动态代理
public class SingleProxy implements InvocationHandler{
//先声明我们要代理的真实对象
private Object person;
//构造方法,给真实对象赋值
public SingleProxy(Object person){
this.person = person;
}
public Object invoke(Object person, Method method, Object[] args) throws Throwable{
//在代理真实对象前,我们可以添加操作进行增强
System.out.println("咱是单身狗");
//调用真实对象的方法
method.invoke(person,args);
//在代理对象之后,依旧可以增强操作
System.out.println("省钱又省心-->别问,问就是等相亲");
return null;
}
}
//主类
public class programmer{
public static void main(String [] args){
//要代理的对象
Man man = new Man();
//将真实对象传入代理类中去
InvocationHandler handler = new SinglerProxy(man);
/*
* 通过Proxy类的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
* 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
* 第二个参数man.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
* 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
Person person = (Person)Proxy.newProxyInstance(handler.getClass().getClassLoader(), man.getClass().getInterfaces(), handler);
person.eat();
person.say();
//这样,动态代理就算完成了
}
}
Java反射机制以及动态代理的更多相关文章
- java反射机制与动态代理
在学习HadoopRPC时.用到了函数调用.函数调用都是採用的java的反射机制和动态代理来实现的,所以如今回想下java的反射和动态代理的相关知识. 一.反射 JAVA反射机制定义: JAVA反射机 ...
- Java反射机制可以动态修改实例中final修饰的成员变量吗?
问题:Java反射机制可以动态修改实例中final修饰的成员变量吗? 回答是分两种情况的. 1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了. ...
- 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】
方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; priva ...
- java.lang.Class<T> -- 反射机制及动态代理
Interface : Person package java_.lang_.component.bean; public interface Person { String area = " ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
- Java的反射机制和动态代理
介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大的功能,可以原 ...
- java反射机制与动态加载类
什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...
- Java中的反射机制和动态代理
一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象 ...
- java反射中的动态代理机制(有实例)
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
随机推荐
- 一键获取linux内存、cpu、磁盘IO等信息脚本编写,及其原理详解
更多linux知识,请关注公众号:一口Linux 一.脚本 今天主要分享一个shell脚本,用来获取linux系统CPU.内存.磁盘IO等信息. #!/bin/bash # 获取要监控的本地服务器IP ...
- 多种细分方式浏览销售数据,IAP助您有效洞察市场收益效果
华为应用内支付服务是直接在应用程序内提供购买商品或订阅等功能,为了能够让开发者更好的了解应用内的销售额及商品购买.订阅的市场收益效果,华为应用内支付服务提供的消费数据统计和数据报表,支持多种细分方式浏 ...
- python报错:AttributeError: module 'pdb' has no attribute 'set_trace'
在第一次使用python中的pdb模块式,pdb.set_trace()时编译器总是会报错,一开始总是以为是自己的拼写错误,但经过反复检查后发现并不是自己的拼写错误.而是我创建的测试文件的名称是pdb ...
- 攻防世界 csaw2013reversing2 CSAW CTF 2014
运行程序 flag显示乱码 IDA打开查看程序逻辑 1 int __cdecl __noreturn main(int argc, const char **argv, const char **en ...
- Kubernetes 常用日志收集方案
Kubernetes 常用日志收集方案 学习了 Kubernetes 集群中监控系统的搭建,除了对集群的监控报警之外,还有一项运维工作是非常重要的,那就是日志的收集. 介绍 应用程序和系统日志可以帮助 ...
- 开源组件编排引擎LiteFlow发布里程碑版本2.5.0
介绍 LiteFlow作为一款轻量级组件编排框架,自开源来,获得了挺多人的关注.社区群也扩展到了接近200人. 早期版本因为疏忽打理,有一些BUG,迭代也不及时.距离上一个稳定版本2.3.3,已经有超 ...
- 【Android实习】20场面试斩获大厂offer,我学会了什么
前言 很高兴遇见你~ 先说一下笔者春招实习的情况:从三月初到四月半,经历了近20场面试,一共面试了五家企业,通过了腾讯.字节.蚂蚁.美团的面试,虎牙在一面之后拒了二面邀请. 金三银四,笔者不是在面试中 ...
- pickle json模块
pickle --- Python 对象序列化 通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储. 通过pickle模块的反序列化操作,我们能够从文件中创建上一次 ...
- 逻辑引擎、工作流、CMDB小感
工作流是啥? 在界面上画画点点就能生成代码,这是很吸引人的事情,也是很多自动化工具追求的目标.工作流就是这么一个东西,通过定义流程和输入,就能实现你想要的东西,不需要编写代码. 工作流的实现 通过解析 ...
- 深入探索Android热修复技术原理读书笔记 —— 热修复技术介绍
1.1 什么是热修复 对于广大的移动开发者而言,发版更新是最为寻常不过的事了.然而,如果你 发现刚发出去的包有紧急的BUG需要修复,那你就必须需要经过下面这样的流程: 这就是传统的更新流程,步骤十分繁 ...