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来满足的 ...
随机推荐
- dfs求连通块
递归 递归是什么?绝大部分人都会说:自己调用自己,刚开始我也是这样理解递归的.确实没错,递归的确是自己调用自己.递归简单的应用:编写一个能计算斐波那契数列的函数,也就是这样: int fb(int n ...
- Linux 三剑客之 awk 实战详解教程
我们知道 Linux 三剑客,它们分别是:grep.sed.awk.在前边已经讲过 grep 和 sed,没看过的同学可以直接点击阅读,今天要分享的是更为强大的 awk. sed 可以实现非交互式的字 ...
- 基于autofac的属性注入
基于autofac的属性注入 什么是属性注入 在了解属性注入之前,要先了解一下DI(Dependency Injection),即依赖注入.在ASP.NET Core里自带了一个IOC容器,而且程序支 ...
- 干掉前端!3分钟纯 Java 注解搭个管理系统
大家好,我是小富~ 最近接触到个新项目,发现它用了一个比较有意思的框架,可以说实现了我刚入行时候的梦想,所以这里马不停蹄的和大家分享下. 在我刚开始工作接触的项目都还没做前后端分离,经常需要后端来维护 ...
- Android学习之 AlertDialog
•AlertDialog简介 AlertDialog 可以在当前界面弹出一个对话框: 这个对话框是置顶于所有界面元素之上的,能够屏蔽掉其他控件的交互能力: 因此, AlertDialog 一般用于提示 ...
- .net 预处理指令符的使用
目录 什么是预处理指令符? 预处理指令符的使用 自定义指令符 使用Visual Studio快速定义指令符 定义指令符区域 什么是预处理指令符? 当C#编译器找到一条预处理指令#if,最后找到一条指令 ...
- 经典变长指令SIB
前言 ModR/M字段是用来进行内存寻址的,可当地址形如DS:[EAX + ECX*2 + 12345678]时,仅仅靠ModR/M字段,是描述不出来的. 这时就在ModR/M后面增加一个SIB字节, ...
- 又一起.NET程序挂死, 用 Windbg 抽丝剥茧式的真实案例分析
一:背景 1. 讲故事 前天有位粉丝朋友在后台留言让我帮忙看看他的 Winform程序 UI无响应 + 410线程 到底是啥情况,如下图: 说实话,能看到这些真实案例我是特别喜欢的 ,就像医生看病,光 ...
- Python中的多进程、多线程和协程
本文中的内容来自我的笔记.撰写过程中参考了胡俊峰老师<Python程序设计与数据科学导论>课程的内容. 并发处理:多进程和多线程 前置 概念: 并发:一段时间内同时推进多个任务,但不一定要 ...
- 观世音甘泉活树的故事竟然是Java设计模式:备忘录模式
目录 定义 意图 主要解决问题 何时使用 优缺点 结构 白箱实现 黑箱实现 多重检查点 观世音甘泉活树的故事 定义 备忘录模式是对象的行为型模式,备忘录对象是一个用来存储另外一个对象内部状态的快照的对 ...