2010-12-08 3 views
9

Java에서 리플렉션을 처리하기위한 오픈 소스 유틸리티 또는 jar 파일이 있습니까?오픈 소스 Java 리플렉션 유틸리티 또는 jar 파일이 있습니까?

클래스에 동적으로 메서드를 전달하고 반환 값을 가져오고 싶습니다. 예를 들어

:이 같은 실행 시간에 그것을 얻는 대신 콘솔 출력에 모든 직원을 인쇄하지만 싶습니다

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

    public String getName() { 
     return name; 
    } 

    public Employee[] getEmployes() { 
     return employees; 

    } 
} 

:

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. 

반사에 어떤 오픈 소스가 있습니까 이런 식으로 수용할까요?

+2

'getEmployes : 말했다되고 그건

, 나는 보통이 더 엔지니어링 방법으로 해결 할 수없는 경우 JXPath는 (http://commons.apache.org/jxpath/users-guide.html가) 문제의 유형에 대한 가장 합리적인 해결책이라고 생각 배열을 반환합니까? '[]]에는'getAddress()'메소드가 없을 것입니다 .. – dacwe

답변

5

이런 종류의 물건은 내가 볼 때 항상 디자인 종소리를 울린다. `) (

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

이것은 매우 흥미로운 접근 방법입니다. 나는 지금까지 JXPath를 몰랐다. 아주 좋아 보인다! –

+0

아주 좋은 방법입니다. – srinannapa

1

당신은 자신을 다른 사람이 제안하는 일부 타사 라이브러리를 사용하거나 수동으로 트릭을 할 수있는, 그렇게 어려운 일이 아니다. 그렇다 나는 반사를 사용하는 상세를 감소 작성한 다른 제안, 당신은 또한, jOOR을 사용할 수, 아파치 BeanUtils를 사용하거나 직접 java.lang.reflect API를 사용

 

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

: 다음 예는 하나가 취할 수있는 방법을 설명한다 Java에서. 귀하의 예는 다음과 같이 구현 될 수있다 :

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

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

자바에서 정상 반사와 같은 예 :

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); 
: 또한

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는 더 편리한 방법으로 java.lang.reflect.Proxy 기능을 래핑

+0

매우 깨끗하고 사용하기 좋은 ez-looking, good job! –

+0

아주 좋아 보이지만 get() 메소드에서 캐스트를 제거하는 것이 좋은가요? 나는 서명이' T get()'이라고 가정하고, 이는 콜 사이트에서 오래된 정직한 캐스트보다 더 많은 문제를 일으킬 수있다. –

+0

@MartinProbst : 네, 서명에 대해 당신 말이 맞아요. 나는 그렇게 나쁜 생각이라고 생각하지 않는다. 'java.util.Collections'에는 두 가지 유사한 경우가 있습니다. –

관련 문제