reflect method getclass from example dynamically java reflection dynamic invoke

method - ¿Hay una biblioteca general de "back-end" para la reflexión de Java?



method invoke java reflection example (10)

Pruebe el módulo de reflexión FEST . Es una forma fluida de hacer la reflexión de Java. Por ejemplo:

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

Actualmente estoy trabajando con un lenguaje de programación especializado e interpretado implementado en Java. Como una parte muy pequeña del lenguaje, me gustaría agregar la capacidad de hacer llamadas a Java. Antes de sumergirme en todo lo esencial de la reflexión, me preguntaba si alguien sabía de una biblioteca general para hacer la parte de "back-end" de invocar código Java reflexivamente.

Es decir, analizo una cadena (defino la gramática) en una estructura de datos que representa una llamada al método Java (o constructor, o acceso de campo) y luego transfiero esa estructura de datos a esta biblioteca que invoca la llamada y devuelve el resultado. En particular, me gustaría que ya maneje todos los casos extremos que no quiero descubrir:

  • Automáticamente elija el método correcto según los tipos de argumentos (como un Class.getDeclaredMethod () inteligente)
  • Manejar la distinción entre arreglos y referencias de objetos normales
  • etc

He dedicado un poco de tiempo a ver las implementaciones de lenguajes dinámicos en la JVM, pero en general son mucho más complicadas de lo que estoy buscando, o están muy optimizadas para el lenguaje en particular.

Otra opción es convertir mi gramática en una cadena en un lenguaje dinámico e invocarlo con Rhino o algo así, pero eso es un poco más elevado de lo que estoy buscando.

¡Gracias!




Terminé yendo con la sugerencia de Alex. BeanUtils ayuda mucho a los frijoles, pero no quiero trabajar únicamente con frijoles. FEST se ve muy bien y lo he marcado para seguir estudiándolo, pero al igual que BeanUtils, no parece resolver lo que considero que es el problema difícil aquí. A saber, dado el nombre de un método y la lista de argumentos, elija el método que mejor se ajuste a los argumentos. Si un método toma un flotante y tengo un doble, debe ser lo suficientemente inteligente como para no rechazar ese método porque la firma no coincide exactamente.

Obviamente, los lenguajes de scripting construidos en la JVM resuelven este problema, pero de una manera mucho más complicada de lo que necesito debido a las optimizaciones específicas del lenguaje. Por lo tanto, como se trata de una característica menor y experimental, he elegido una solución expedita utilizando el soporte del motor de scripting (JavaScript, en particular) en Java 1.6. Aquí está la idea básica:

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('')''); }

Obviamente, hay un poco más, pero esta es la idea básica. Realmente no me gusta construir una cuerda y evaluarla, pero al usar las ataduras sugeridas por Alex, evito la mayoría de las trampas que escapan. Además, tengo una interfaz limpia y simple que puedo intercambiar con una implementación "real" si resulta necesario.

Cualquier comentario o solución alternativa son más que bienvenidos.


Consideraría también echar un vistazo a la clase ReflectionUtils de Springs. Muy poderoso manejo de la reflexión.


PARA levantar esto de los muertos:

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

Apache Commons Lang tiene exactamente ese método. MethodUtils # invoke



Empecé a crear una biblioteca com.lexicalscope.fluent-reflection: fluent-reflection que se integra con hamcrest y lambdaj

Puedes escribir código como este; que llama a todos los métodos anotados posteriores a la construcción en una clase:

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

Publicación del blog aquí: http://www.lexicalscope.com/blog/category/software-projects/fluent-reflection/

Documentación aquí: http://fluent-reflection.lexicalscope.com/

Puede obtenerlo desde Maven Central aquí: http://repo1.maven.org/maven2/com/lexicalscope/fluent-reflection/fluent-reflection/

Tiene algunas características básicas que faltan en este momento, como el acceso a los campos, pero funciona para los métodos. Probablemente demore un tiempo llegar a un punto estable en realidad (como uno o dos años), ya que solo estoy trabajando ocasionalmente. Pero está desarrollado con un estándar de calidad bastante alto (espero) y es de código abierto, así que básicamente puedes usarlo tal como está ahora si tiene todas las características que necesitas (es posible que tengas que ajustar tu código un poco si quieres para usar las versiones más nuevas que se lanzan). Lo estoy usando en algún código de producción en ese momento.

Está diseñado para ser bastante extensible, por lo que puede agregar estrategias para encontrar los métodos que desea en un estilo poco articulado (de composición). Por lo tanto, si no tiene la estrategia exacta de búsqueda de métodos que desea, es de esperar que sea fácil de agregar.


Si está buscando la simplicidad, he creado una biblioteca simple llamada jOOR para facilitar el acceso a la API de reflexión en Java. Es compatible con las acciones más esenciales sin construir una gran API. Aquí hay un ejemplo de cómo se ve el código 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


Solo un comentario a tu propia respuesta; en realidad beanutils tiene soporte para obtener "una coincidencia cercana" dado un conjunto de parámetros. Ver getMatchingAccessibleMethod ()

BeanUtils es realmente potente y tiene muchos métodos de utilidad para inspeccionar clases. El mismo soporte está naturalmente disponible para los constructores.