服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - java 非常好用的反射框架Reflections介绍

java 非常好用的反射框架Reflections介绍

2021-09-02 12:44wei906 Java教程

这篇文章主要介绍了java 反射框架Reflections的使用,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据。

使用Reflections可以很轻松的获取以下元数据信息:

1)获取某个类型的所有子类;比如,有一个父类是TestInterface,可以获取到TestInterface的所有子类。

2)获取某个注解的所有类型/字段变量,支持注解参数匹配。

3)使用正则表达式获取所有匹配的资源文件

4)获取特定签名方法。

通常的用法有:

引入依赖jar

  1. <dependency>
  2. <groupId>org.reflections</groupId>
  3. <artifactId>reflections</artifactId>
  4. <version>0.9.10</version>
  5. </dependency>

项目中使用:

  1. // 初始化工具类
  2. Reflections reflections = new Reflections(new ConfigurationBuilder().forPackages(basePackages).addScanners(new SubTypesScanner()).addScanners(new FieldAnnotationsScanner()));
  3.  
  4. // 获取某个包下类型注解对应的类
  5. Set<Class<?>> typeClass = reflections.getTypesAnnotatedWith(RpcInterface.class, true);
  6.  
  7. // 获取子类
  8. Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
  9.  
  10. // 获取注解对应的方法
  11. Set<Method> resources =reflections.getMethodsAnnotatedWith(SomeAnnotation.class);
  12.  
  13. // 获取注解对应的字段
  14. Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);
  15.  
  16. // 获取特定参数对应的方法
  17. Set<Method> someMethods = reflections.getMethodsMatchParams(long.class, int.class);
  18.  
  19. Set<Method> voidMethods = reflections.getMethodsReturn(void.class);
  20.  
  21. Set<Method> pathParamMethods =reflections.getMethodsWithAnyParamAnnotated(PathParam.class);
  22.  
  23. // 获取资源文件
  24. Set<String> properties = reflections.getResources(Pattern.compile(".*\\.properties"));

具体也可以参见官方文档

补充:Java中的反射:框架设计的灵魂

反射:框架设计的灵魂

框架:半成品软件。可以在框架的基础上进行软件开发,简化编码

反射:将类的各个组成部分封装为其他对象,这就是反射机制

好处:

1.可以在程序运行过程中,操作这些对象。

2.可以解耦,提高程序的可扩展性。

获取Class对象的方式:

1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象

多用于配置文件,将类名定义在配置文件中。读取文件,加载类

2.类名.class:通过类名的属性class获取

多用于参数的传递

3.对象.getClass():getClass()方法在Object类中定义着。

多用于对象的获取字节码的方式

结论:

同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

例如我们有一个Person类

  1. public class Person {
  2. private String name;
  3. private int age;
  4. public Person(){
  5. }
  6. public Person(String name, int age) {
  7. this.name = name;
  8. this.age = age;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Person{" +
  25. "name='" + name + '\'' +
  26. ", age=" + age +
  27. '}';
  28. }
  29. }

我们写一个Demo用三种方式来获取Class对象

  1. public class Demo1 {
  2. public static void main(String [] args) throws Exception {
  3. //1、Class.forName("类名")
  4. Class cls1 = Class.forName("man.Person");
  5. System.out.println(cls1);
  6. //2、类名。class
  7. Class cls2= Person.class;
  8. System.out.println(cls2);
  9. //3、对象.getClass()
  10. Person p = new Person();
  11. Class cls3=p.getClass();
  12. System.out.println(cls3);
  13. }
  14. }

Class对象功能:

获取功能:

1.获取成员变量们

Field[] getFields() :获取所有public修饰的成员变量

Field getField(String name) 获取指定名称的 public修饰的成员变量

Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符

  1. Field getDeclaredField(String name)

2.获取构造方法们

  1. Constructor<?>[] getConstructors()
  2. Constructor getConstructor(类<?>… parameterTypes)
  3. Constructor getDeclaredConstructor(类<?>… parameterTypes)
  4. Constructor<?>[] getDeclaredConstructors()

3.获取成员方法们:

  1. Method[] getMethods()
  2. Method getMethod(String name, 类<?>… parameterTypes)
  3. Method[] getDeclaredMethods()
  4. Method getDeclaredMethod(String name, 类<?>… parameterTypes)

4.获取全类名

String getName() * Field:成员变量

操作:

5.设置值

  1. void set(Object obj, Object value)

6.获取值

  1. get(Object obj)

7.忽略访问权限修饰符的安全检查

setAccessible(true):暴力反射

Constructor:构造方法

创建对象:

  1. T newInstance(Object initargs)

如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法* Method:方法对象

执行方法:

  1. Object invoke(Object obj, Object args)

获取方法名称:

String getName:获取方法名

同样对于上面的Person类我们对其新增带参数和不带参数的sleep方法并且写一个Demo来获取这些成员变量,构造方法以及成员方法

Person.java

  1. public class Person {
  2. private String name;
  3. private int age;
  4. public String a;
  5. protected String b;
  6. String c;
  7. private String d;
  8. public Person(){
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. public Person(String name, int age) {
  23. this.name = name;
  24. this.age = age;
  25. }
  26. public void eat(){
  27. System.out.println("eat...");
  28. }
  29. public void eat(String food){
  30. System.out.println("eat..."+food);
  31. }
  32. @Override
  33. public String toString() {
  34. return "Person{" +
  35. "name='" + name + '\'' +
  36. ", age=" + age +
  37. ", a='" + a + '\'' +
  38. ", b='" + b + '\'' +
  39. ", c='" + c + '\'' +
  40. ", d='" + d + '\'' +
  41. '}';
  42. }
  43. }

Demo2.java代码如下:

  1. public class Demo2 {
  2. public static void main(String [] args) throws Exception {
  3. Class<Person> personClass = Person.class;
  4. //获取成员变量
  5. Field[] fields = personClass.getFields();
  6. for(Field field:fields) {
  7. System.out.println(field);
  8. }
  9. System.out.println("--------------");
  10. Field a = personClass.getField("a");//获取a的值
  11. Person p = new Person();
  12. Object value=a.get(p);
  13. System.out.println(value);
  14. a.set(p, "zhangsan");//设置a的值
  15. System.out.println(p);
  16. System.out.println("=============");
  17. //获取所有成员变量
  18. Field[] declaredFields = personClass.getDeclaredFields();
  19. for (Field declaredField : declaredFields) {
  20. System.out.println(declaredField);
  21. }
  22. Field d = personClass.getDeclaredField("d");
  23. d.setAccessible(true);//暴力反射
  24. Object value2 = d.get(p);
  25. System.out.println(value2);
  26. //获取构造方法
  27. Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
  28. System.out.println(constructor);
  29. Object person = constructor.newInstance("张三", 23);
  30. System.out.println(person);
  31. System.out.println("=======");
  32. Constructor<Person> constructor1 = personClass.getConstructor();
  33. System.out.println(constructor1);
  34. Object person1 = constructor1.newInstance();
  35. System.out.println(person1);
  36. //获取成员方法
  37. Method eat_method = personClass.getMethod("eat");
  38. Person p1 = new Person();
  39. eat_method.invoke(p1);
  40. Method eat_method1 = personClass.getMethod("eat",String.class);
  41. eat_method1.invoke(p1,"饭");
  42. System.out.println("---------");
  43. Method[] methods = personClass.getMethods();
  44. for (Method method : methods) {
  45. System.out.println(method);
  46. }
  47. }
  48. }

运行结果如下:

  1. public java.lang.String man.Person.a
  2. -------------- null Person{name=‘null', age=0, a=‘zhangsan', b=‘null', c=‘null', d=‘null'}
  3. ============= private java.lang.String man.Person.name private int man.Person.age public java.lang.String man.Person.a protected
  4. java.lang.String man.Person.b java.lang.String man.Person.c private
  5. java.lang.String man.Person.d null public
  6. man.Person(java.lang.String,int) Person{name=‘张三', age=23, a=‘null',
  7. b=‘null', c=‘null', d=‘null'}
  8. ======= public man.Person() Person{name=‘null', age=0, a=‘null', b=‘null', c=‘null', d=‘null'} eat… eat…饭
  9. --------- public java.lang.String man.Person.toString() public java.lang.String man.Person.getName() public void
  10. man.Person.setName(java.lang.String) public void
  11. man.Person.eat(java.lang.String) public void man.Person.eat() public
  12. void man.Person.setAge(int) public int man.Person.getAge() public
  13. final void java.lang.Object.wait() throws
  14. java.lang.InterruptedException public final void
  15. java.lang.Object.wait(long,int) throws java.lang.InterruptedException
  16. public final native void java.lang.Object.wait(long) throws
  17. java.lang.InterruptedException public boolean
  18. java.lang.Object.equals(java.lang.Object) public native int
  19. java.lang.Object.hashCode() public final native java.lang.Class
  20. java.lang.Object.getClass() public final native void
  21. java.lang.Object.notify() public final native void
  22. java.lang.Object.notifyAll()

案例

需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法

实现:

1. 配置文件

2. 反射

步骤:

1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中

2. 在程序中加载读取配置文件

3. 使用反射技术来加载类文件进内存

4. 创建对象

5. 执行方法

为了实现创建任意类的对象,并且执行其中任意方法,我们再原有Person.java文件基础上新增Student.java,代码如下:

  1. public class Student {
  2. public void sleep(){
  3. System.out.println("sleep...");
  4. }
  5. }

那么我们需要在src目录下添加pro.properties文件并写入以下配置信息

  1. className=man.Student
  2. methodName=sleep

接着我们来写这个案例ReflectTest.java,代码如下

  1. public class ReflectTest {
  2. public static void main(String [] args) throws Exception {
  3. //加载配置文件
  4. Properties pro = new Properties();
  5. ClassLoader classLoader = ReflectTest.class.getClassLoader();
  6. InputStream is = classLoader.getResourceAsStream("pro.properties");
  7. pro.load(is);
  8. //获取配置文件中定义的数据
  9. String className = pro.getProperty("className");
  10. String methodName = pro.getProperty("methodName");
  11. //加载该类进内存
  12. Class cls = Class.forName(className);
  13. Object obj = cls.newInstance();
  14. Method method = cls.getMethod(methodName);
  15. method.invoke(obj);
  16. }
  17. }

这样我们只需改变配置文件中的信息而不需要去改变任何代码就可以实现类以及类中的方法​,整个目录结构如下

java 非常好用的反射框架Reflections介绍

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

原文链接:https://blog.csdn.net/chenwiehuang/article/details/83114641

延伸 · 阅读

精彩推荐
  • Java教程xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下...

    Java教程网2942020-09-17
  • Java教程小米推送Java代码

    小米推送Java代码

    今天小编就为大家分享一篇关于小米推送Java代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    富贵稳中求8032021-07-12
  • Java教程20个非常实用的Java程序代码片段

    20个非常实用的Java程序代码片段

    这篇文章主要为大家分享了20个非常实用的Java程序片段,对java开发项目有所帮助,感兴趣的小伙伴们可以参考一下 ...

    lijiao5352020-04-06
  • Java教程Java实现抢红包功能

    Java实现抢红包功能

    这篇文章主要为大家详细介绍了Java实现抢红包功能,采用多线程模拟多人同时抢红包,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java BufferWriter写文件写不进去或缺失数据的解决

    Java BufferWriter写文件写不进去或缺失数据的解决

    这篇文章主要介绍了Java BufferWriter写文件写不进去或缺失数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望...

    spcoder14552021-10-18
  • Java教程升级IDEA后Lombok不能使用的解决方法

    升级IDEA后Lombok不能使用的解决方法

    最近看到提示IDEA提示升级,寻思已经有好久没有升过级了。升级完毕重启之后,突然发现好多错误,本文就来介绍一下如何解决,感兴趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java8中Stream使用的一个注意事项

    Java8中Stream使用的一个注意事项

    最近在工作中发现了对于集合操作转换的神器,java8新特性 stream,但在使用中遇到了一个非常重要的注意点,所以这篇文章主要给大家介绍了关于Java8中S...

    阿杜7472021-02-04
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    这篇文章主要介绍了Java使用SAX解析xml的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下...

    大行者10067412021-08-30