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反射机制以及动态代理的更多相关文章

  1. java反射机制与动态代理

    在学习HadoopRPC时.用到了函数调用.函数调用都是採用的java的反射机制和动态代理来实现的,所以如今回想下java的反射和动态代理的相关知识. 一.反射 JAVA反射机制定义: JAVA反射机 ...

  2. Java反射机制可以动态修改实例中final修饰的成员变量吗?

    问题:Java反射机制可以动态修改实例中final修饰的成员变量吗? 回答是分两种情况的. 1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了. ...

  3. 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】

    方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; priva ...

  4. java.lang.Class<T> -- 反射机制及动态代理

    Interface : Person package java_.lang_.component.bean; public interface Person { String area = " ...

  5. 【Java基础】java中的反射机制与动态代理

    一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...

  6. Java的反射机制和动态代理

    介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大的功能,可以原 ...

  7. java反射机制与动态加载类

    什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...

  8. Java中的反射机制和动态代理

    一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象 ...

  9. java反射中的动态代理机制(有实例)

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

随机推荐

  1. BZOJ_2115 [Wc2011] Xor 【图上线性基】

    一.题目 [Wc2011] Xor 二.分析 比较有意思的一题,这里也学到一个结论:$1$到$N$的任意一条路径异或和,可以是一个任意一条$1$到$N$的异或和与图中一些环的异或和组合得到.因为一个数 ...

  2. 2019看雪CTF 晋级赛Q2第四题wp

    上次参加2019看雪CTF 晋级赛Q2卡在了这道题上,虽然逆出算法,但是方程不会解,哈哈哈哈,果然数学知识很重要呀,现在记录一下. 首先根据关键信息,根据错误提示字符串定位到这里: 1 int __t ...

  3. 生产中常用的du命令

    1. 介绍 du是用来查看文件或目录所占用磁盘空间的大小 du [-abcDhHklmsSx] [-L <符号连接>][-X <文件>][--block-size][--exc ...

  4. angularjs 图片上传

    <input type="file" file-model="myFile"/><div class="col-md-12" ...

  5. 【oracle学习笔记01】oracle architecture —— Memory Strucrure

    附图3: granule_size for each components 附图4:

  6. 201871030119-马桂婷 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

    项目 内容 课程班级博客 2018卓越工程师班 这个作业要求链接 实验三 软件工程结对项目 我的课程学习目标 1.体验软件项目开发中的两人合作,练习结对编程:2.掌握Github协作开发程序的操作方法 ...

  7. (十六)Struts2的标签库

    一.简介 Struts2的标签库使用OGNL为基础,大大简化了数据的输出,也提供了大量标签来生成页面效果,功能非常强大. 在早期的web应用开发中,jsp页面主要使用jsp脚本来控制输出.jsp页面嵌 ...

  8. SQLlite实现增删查改

    activity_main.xml文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android ...

  9. 五年了,你还在用Junit4吗?

    junit5 JUnit5在2017年就发布了,你还在用junit4吗? 什么是junit5 与以前的JUnit版本不同,JUnit 5由三个不同子项目的多个不同模块组成. JUnit 5 = JUn ...

  10. linux 在某个路径下,查找某个文件

    find /cephfs/netdisk/ -name "*.sql"