是否有一个用于Javareflection的通用“后端”库

我目前正在使用Java实现的专用解释编程语言。 作为语言的一小部分,我想添加调用Java的能力。 在深入研究reflection的所有细节之前,我想知道是否有人知道有一个通用库来执行反向调用Java代码的“后端”部分。

也就是说,我将一个字符串(我定义语法)解析为一些表示Java方法调用(或构造函数或字段访问)的数据结构,然后将该数据结构传递给调用该调用并返回结果的库。 特别是,我希望它已经处理了我不想弄清楚的所有边缘情况:

  • 根据参数类型自动选择正确的方法(如智能Class.getDeclaredMethod())
  • 处理数组和普通对象引用之间的区别
  • 等等

我花了一点时间在JVM上查看动态语言的实现,但这些通常比我正在寻找的要复杂得多,或者针对特定语言进行了高度优化。

另一种选择是将我的语法转换为某种动态语言的字符串,并使用Rhino或其他东西调用它,但这比我正在寻找的开销稍微多一些。

谢谢!

只是评论你自己的答案; 实际上,beanutils支持在给定一组参数的情况下获得“紧密匹配”。 请参阅getMatchingAccessibleMethod()

BeanUtils非常强大,并且有许多用于检查类的实用方法。 构造函数自然可以获得相同的支持。

尝试FEST Reflection模块。 这是一种流畅的Javareflection方式。 例如:

String name = method("get").withReturnType(String.class) .withParameterTypes(int.class) .in(names) .invoke(8); 

看看Java的脚本支持 ; 我相信它会帮助你解决问题。

看看Apache Commons BeanUtils

如果您正在寻找简单性,我创建了一个名为jOOR的简单库,以便于访问Java中的reflectionAPI。 它支持最基本的操作,而无需构建庞大的API。 以下是jOOR代码的示例:

 String world = on("java.lang.String") // Like Class.forName() .create("Hello World") // Call the most specific matching constructor .call("substring", 6) // Call the most specific matching substring() method .call("toString") // Call toString() .get() // Get the wrapped object, in this case a String 

我强烈考虑看一下Spring的ReflectionUtils类。 非常强大的reflection处理。

从死里复活:

 invoke(Object object, String methodName, Object[] args) 

Apache Commons lang正是这种方法。 MethodUtils#调用

我已经开始创建一个库com.lexicalscope.fluent-reflection:fluent-reflection,它与hamcrest和lambdaj集成在一起

你可以写这样的代码; 它调用类中的所有post构造注释方法:

 forEach( object(subject).methods(annotatedWith(PostConstruct.class)), ReflectedMethod.class).call(); 

博客文章: http : //www.lexicalscope.com/blog/category/software-projects/fluent-reflection/

文档: http : //fluent-reflection.lexicalscope.com/

您可以从maven central获取它: http : //repo1.maven.org/maven2/com/lexicalscope/fluent-reflection/fluent-reflection/

它目前缺少一些基本function,比如访问字段,但它适用于方法。 它可能需要一段时间才能达到一个非常稳定的function点(比如一年或两年),因为我偶尔会处理它。 但是它被开发成相当高质量的标准(我希望)并且它是开源的,所以你现在基本上可以使用它,如果它具有你需要的所有function(你可能需要调整你的代码,如果你想使用已发布的较新版本。 我现在在一些生产代码中使用它。

它的设计非常易于扩展,因此您可以插入策略,以松散耦合(组合)的方式查找所需的方法。 因此,如果它没有您想要的确切方法查找策略,希望很容易添加它。

我最终得到了亚历克斯的建议。 BeanUtils对bean很有帮助,但我不想单独使用Beans。 FEST看起来非常酷,我已将它标记为进一步研究,但是像BeanUtils一样,它似乎并没有解决我认为这里的难题。 也就是说,给定方法名称和参数列表,选择最适合参数的方法。 如果一个方法采用浮点数并且我有一个double,那么它应该足够聪明,不要拒绝该方法,因为签名不完全匹配。

显然,构建在JVM上的脚本语言解决了这个问题,但由于语言特定的优化,它的方式比我需要的要复杂得多。 因此,由于这是一个次要的实验性function,我选择了使用Java 1.6中的脚本引擎支持(特别是JavaScript)的快速解决方案。 这是基本的想法:

 private ScriptEngine engine = ... initialize with JavaScript engine ... private Object invoke(Object object, String methodName, Object[] args) throws RhsFunctionException { // build up "o.method(arg0, arg1, arg2, ...)" StringBuilder exp = new StringBuilder("o." + methodName); engine.put("o", object); buildArgs(arguments, exp); try { return engine.eval(exp.toString()); } catch (ScriptException e) { throw new RhsFunctionException(e.getMessage(), e); } } private void buildArgs(Object[] args, StringBuilder exp) { // Use bindings to avoid having to escape arguments exp.append('('); int i = 0; for(Symbol arg : args) { String argName = "arg" + i; engine.put(argName, arg); if(i != 0) { exp.append(','); } exp.append(argName); ++i; } exp.append(')'); } 

显然还有一点,但这是基本的想法。 我真的不喜欢建立一个字符串并对其进行评估,但是通过使用Alex建议的绑定,我避免了逃逸时的大部分陷阱。 此外,我有一个干净,简单的界面,如果certificate有必要,我可以用“真正的”实现交换。

任何反馈或替代解决方案都非常受欢迎。

我在阅读完这个post后编写并开源了这段代码,也许你会发现它很有用。

https://github.com/yclian/Reflects.java/blob/master/src/test/java/my/jug/reflects/ReflectsTest.java

它的灵感来自Guava,因此您可以使用Predicate来过滤您喜欢的方法。