Java效率提升神器jOOR
前言
Java中的原生反射库虽然方法不多,但写起来却非常繁琐, 比如:
public static <T> T create(HttpRequest httpRequest) { Object httpRequestEntity = null; try { Class<T> httpRequestEntityCls = (Class<T>) Class.forName(HttpProcessor.PACKAGE_NAME + "." + HttpProcessor.CLASS_NAME); Constructor con = httpRequestEntityCls.getConstructor(HttpRequest.class); httpRequestEntity = con.newInstance(httpRequest); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return (T) httpRequestEntity; }
就实现一个对象的构造都需要写一长串代码,特别是异常处理非常污染视觉。
发现有一个第三方库:jOOR,通过链式DSL接口,简化了反射过程,
比如:
@Test void should_get_World() { String result = Reflect.onClass("java.lang.String") // 类似Class.forName() .create("Hello World") // 调用构造器 .call("substring", 6) // 调用方法 .call("toString") // 调用方法 .get(); // 获取最终包装类 assertThat(result).isEqualTo("World"); }
再比如:原有java代码写法:
try { Method m1 = department.getClass().getMethod("getEmployees"); Employee employees = (Employee[]) m1.invoke(department); for (Employee employee : employees) { Method m2 = employee.getClass().getMethod("getAddress"); Address address = (Address) m2.invoke(employee); Method m3 = address.getClass().getMethod("getStreet"); Street street = (Street) m3.invoke(address); System.out.println(street); } } // There are many checked exceptions that you are likely to ignore anyway catch (Exception ignore) { // ... or maybe just wrap in your preferred runtime exception: throw new RuntimeException(e); }
采用jOOR后的写法:
Employee[] employees = on(department).call("getEmployees").get(); for (Employee employee : employees) { Street street = on(employee).call("getAddress").call("getStreet").get(); System.out.println(street); }
已经非常的简洁了。
jOOR特点
- 提供on()操作符对类名、Class、Object进行统一实例化为Reflect对象,后续所有的反射操作基于该Reflect对象。
- 所有功能调用方式均被封装成返回Reflect对象的链式结构,在使用上使得代码更加简洁。
- 对方法的签名匹配封装了更完善的匹配规则,包括精确匹配exactMethod()、近似匹配similarMethod()【对函数参数的近似匹配(int -> Integer)】和基类搜索等。
- 调用私有方法的不需要显示调用setAccessible(),内部动态读取public标记自动适配。
- 更加简洁的实现了对象构造函数的反射调用create()方法。
- 函数的调用call()方法组合成了可以拼接在Reflect的对象后面的链式方法。
- 额外增加了高级操作符as(),它实现了类的代理访问以及POJO对象的get/set/is方法实现。
常用API测试
测试类:
class Person { private String name; private int age; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
测试APIS
@Test void test_joor_apis() { // 【创建类】 Person person = Reflect.onClass(Person.class).create("steven").get();// 有参构造器 //Person person = Reflect.onClass(Person.class).create().get(); // 无参构造器 assertThat(person.toString()).isEqualTo("Person{name='steven', age=0}"); // 【调用方法】 Reflect.on(person).call("setName", "steven2"); String name = Reflect.on(person).call("getName").toString(); assertThat(name).isEqualTo("steven2"); // 【设置变量的值】 int age = Reflect.on(person).set("age", 18).get("age"); assertThat(age).isEqualTo(18); // 【得到变量】 name = Reflect.on(person).field("name").get();// 方式一 assertThat(name).isEqualTo("steven2"); name = Reflect.on(person).get("name");// 方式二 assertThat(name).isEqualTo("steven2"); }
代理功能
jOOR代理是实现的静态代理功能,首先创建静态代理相关类
interface HelloWorld { void print(); } class HelloWorldImpl implements HelloWorld { public void print() { System.out.println("Hello World"); } } class StaticProxy implements HelloWorld { private HelloWorld helloWorld; public StaticProxy(HelloWorld helloWorld) { this.helloWorld = helloWorld; } public void print() { System.out.println("Before Hello World!"); helloWorld.print(); System.out.println("After Hello World!"); } }
使用方法区别:
传统方式:
@Test void test_proxy_normal() { StaticProxy staticProxy = new StaticProxy(new HelloWorldImpl()); staticProxy.print(); }
jOOR实现方式
@Test void test_proxy_jOOR() { Reflect.onClass(StaticProxy.class)//反射调用StaticProxy .create(new HelloWorldImpl())//调用构造器 .as(HelloWorld.class)//作为HelloWorld接口的代理 .print(); }
此时要求代理类和业务类具有相同的方法,才能通过调用代理的方法,负责抛出ReflectException
异常
org.joor.ReflectException: java.lang.NoSuchMethodException: No similar method print with params [] could be found on type class StaticProxy. at org.joor.Reflect.call(Reflect.java:585) at org.joor.Reflect$1.invoke(Reflect.java:756)
特殊情况
当业务类为map类型,此时会把POJO的getter和setter转换成map的put和get
// [#14] Emulate POJO behaviour on wrapped map objects catch (ReflectException e) { if (isMap) { Map<String, Object> map = (Map<String, Object>) object; int length = (args == null ? 0 : args.length); if (length == 0 && name.startsWith("get")) { return map.get(property(name.substring(3))); } else if (length == 0 && name.startsWith("is")) { return map.get(property(name.substring(2))); } else if (length == 1 && name.startsWith("set")) { map.put(property(name.substring(3)), args[0]); return null; } }
动态编译
jOOR提供了可选的依赖java.compiler
可以简化 javax.tools.JavaCompiler
编译代码,
如下所示:
@Test void test_compile_on_runtime() { Supplier<String> supplier = Reflect.compile( "com.example.HelloWorld", "package com.example;\n" + "class HelloWorld implements java.util.function.Supplier<String> {\n" + " public String get() {\n" + " return \"Hello World!\";\n" + " }\n" + "}\n").create().get(); String result = supplier.get(); assertThat(result).isEqualTo("Hello World!"); }
结论
通过以上案例可以看出,jOOR由于其链式编程的特性,对代码的简化和可扩展性要强Java自带反射库和其他第三方库(apache、hutool等),且其包含了一些高级应用,如代理等。
- 简化了私有方法的反射调用
- 简化了反射冗长的异常处理。
- 简化了对Class、Method、Field、Constructor反射类的实例化,改为统一Reflect替换。
- 链式调用方式更简洁明了
到此这篇关于Java效率提升神器jOOR的文章就介绍到这了,更多相关Java jOOR内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://juejin.cn/post/7112462881651687431
相关文章
- 这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
java 运行报错has been compiled by a more recent version of the Java Runtime
java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)...2021-04-01- 这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了教你怎么用Java获取国家法定节假日,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-23
- 这篇文章主要介绍了Java如何发起http请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-31
- 说起C#和Java这两门语言(语法,数据类型 等),个人以为,大概有90%以上的相似,甚至可以认为几乎一样。但是在工作中,我也发现了一些细微的差别...2020-06-25
- 这篇文章主要介绍了解决Java处理HTTP请求超时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
- 这篇文章主要介绍了java 判断两个时间段是否重叠的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 关于mysql效率优化一般通过以下两种方式定位执行效率较低的sql语句。通过慢查询日志定位那些执行效率较低的 SQL 语句,用 --log-slow-queries[=file_name] 选项启动时, mysqld 会 写一个包含所有执行时间超过 long_quer...2015-11-08
- 这篇文章主要介绍了超简洁java实现双色球若干注随机号码生成(实例代码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-02
- 这篇文章主要介绍了Java生成随机姓名、性别和年龄的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-01
java 画pdf用itext调整表格宽度、自定义各个列宽的方法
这篇文章主要介绍了java 画pdf用itext调整表格宽度、自定义各个列宽的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-31- 这篇文章主要介绍了java正则表达式判断前端参数修改表中另一个字段的值,需要的朋友可以参考下...2021-05-07
Java使用ScriptEngine动态执行代码(附Java几种动态执行代码比较)
这篇文章主要介绍了Java使用ScriptEngine动态执行代码,并且分享Java几种动态执行代码比较,需要的朋友可以参考下...2021-04-15- 这篇文章主要介绍了Java开发实现人机猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-03
- 这篇文章主要介绍了Java List集合返回值去掉中括号('[ ]')的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-29
Java中lombok的@Builder注解的解析与简单使用详解
这篇文章主要介绍了Java中lombok的@Builder注解的解析与简单使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-06- 下面小编就为大家带来一篇java中String类型变量的赋值问题介绍。小编觉得挺不错的。现在分享给大家,给大家一个参考。...2016-03-28
Java 8 Stream 的终极技巧——Collectors 功能与操作方法详解
这篇文章主要介绍了Java 8 Stream Collectors 功能与操作方法,结合实例形式详细分析了Java 8 Stream Collectors 功能、操作方法及相关注意事项,需要的朋友可以参考下...2020-05-20- 这篇文章主要介绍了Java线程池中的各个参数如何合理设置操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-19