2010-12-08 17 views
9

¿Existe alguna utilidad de fuente abierta o jar para manejar la reflexión en Java?¿Hay utilidades o jarras de reflexión Java de código abierto?

Estoy pasando los métodos dinámicamente a una clase y me gustaría obtener el valor de retorno.

Por ejemplo:

class Department { 
    String name ; 
    Employee[] employees; 
    public void setName(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

    public Employee[] getEmployes() { 
     return employees; 

    } 
} 

quisiera imprimir todos los empleados a la salida de la consola, sino conseguir que en tiempo de ejecución así:

Department dept = new Department(); 
// add employees.. 

getEmployeeNames(dept,"getEmployees.getAddress.getStreet"); 
// So the user says they want employee street, but we don't know that 
// until run-tme. 

¿Hay alguna fuente abierta en la reflexión para acomodar algo como esto?

+2

'getEmployes()' devuelve una matriz? No habrá un método 'getAddress()' en un '[]' .. – dacwe

Respuesta

5

Este tipo de cosas siempre suena el diseño de campanas de alarma cuando lo veo.

Dicho esto, por lo general piensan que JXPath (http://commons.apache.org/jxpath/users-guide.html) es la solución más razonable para ese tipo de problema si no se puede resolver de una manera más Engineered:

import org.apache.commons.jxpath.JXPathContext; 

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.List; 

/** 
*/ 
public class JXPather { 
    public static void main(String[] args) { 
     Department d = new Department(); 
     d.employees.add(new Employee(new Address("wherever a"))); 
     d.employees.add(new Employee(new Address("wherever b"))); 
     d.employees.add(new Employee(new Address("wherever c"))); 
     d.employees.add(new Employee(new Address("wherever def"))); 

     JXPathContext context = JXPathContext.newContext(d); 
     // access matched xpath objects by iterating over them 
     for (Iterator iterator = context.iterate("/employees/address/street"); iterator.hasNext();) { 
      System.out.println(iterator.next()); 
     } 

     // or directly via standard xpath expressions 

     System.out.println("street of third employee is: "+context.getValue("/employees[3]/address/street")); 

     // supports most (or all ?) xpath expressions 

     for (Iterator iterator = context.iterate("/employees/address/street[string-length(.) > 11]"); iterator.hasNext();) { 
      System.out.println("street length longer than 11 c'ars:"+iterator.next()); 
     } 
    } 

    static public class Department { 
     List<Employee> employees = new ArrayList<Employee>(); 
     public List<Employee> getEmployees() { 
      return employees; 
     } 
    } 

    static public class Employee { 
     Address address; 
     Employee(Address address) { 
      this.address = address; 
     } 
     public Address getAddress() { 
      return address; 
     } 

    } 

    static public class Address { 
     String street; 
     Address(String street) { 
      this.street = street; 
     } 
     public String getStreet() { 
      return street; 
     } 
    } 

} 
+0

. Es un enfoque muy interesante. No conocía JXPath hasta ahora. Se ve muy bien! –

+0

Muy buen enfoque. – srinannapa

1

Usted puede utilizar alguna biblioteca de terceros como otros sugieren o puede hacer el truco manualmente a sí mismo, no es tan difícil. El siguiente ejemplo debe ilustrar la forma en que se podría tomar:

 

class Department { 
    Integer[] employees; 
    public void setEmployes(Integer[] employees) { this.employees = employees; } 
    public Integer[] getEmployees() { return employees; } 
} 

Department dept = new Department(); 
dept.setEmployes(new Integer[] {1, 2, 3}); 
Method mEmploees = Department.class.getMethod("getEmployees", new Class[] {}); 
Object o = mEmploees.invoke(dept, new Object[] {}); 
Integer[] employees = (Integer[])o; 
System.out.println(employees[0].doubleValue());; 
 
20

Aparte de utilizar Apache BeanUtils o utilizando directamente la API java.lang.reflect, como otros sugirieron, también se puede utilizar jOOR, que he creado para disminuir el nivel de detalle de la utilización de la reflexión en Java. Su ejemplo podría entonces ser implementada como esto:

Employee[] employees = on(department).call("getEmployees").get(); 

for (Employee employee : employees) { 
    Street street = on(employee).call("getAddress").call("getStreet").get(); 
    System.out.println(street); 
} 

El mismo ejemplo con la reflexión normales en 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); 
} 

Además, Joor envuelve la funcionalidad java.lang.reflect.Proxy de una manera más conveniente:

interface StringProxy { 
    String mySubString(int beginIndex); 
} 

// You can easily create a proxy of a custom type to a jOOR-wrapped object 
String substring = on("java.lang.String") 
        .create("Hello World") 
        .as(StringProxy.class) 
        .mySubString(6); 
+0

¡Muy limpio y fácil de usar, buen trabajo! –

+0

Se ve muy bien, pero ¿está seguro de que es una buena idea generar el descarte en los métodos get()? Supongo que la firma es ' T get()', que podría causar más problemas que un buen reparto honesto en el sitio de llamadas. –

+0

@MartinProbst: Sí, tiene razón sobre la firma. No creo que sea una mala idea. 'java.util.Collections' tiene un par de casos similares ... –

Cuestiones relacionadas