2013-01-24 9 views
10

Trong Java, làm thế nào để bạn nhận được đối tượng lớp gốc và/hoặc tên lớp của proxy Java EE (CDI)?Tên lớp gốc của proxy (không có thao tác chuỗi thủ công)

Khi sử dụng getName() về một trường hợp proxy, tên trở lại là một cái gì đó giống như

com.company.employeemgmt.EmployeeManager$Proxy$_$$_WeldSubclass 

Có một số functionaliy trong Java SE (7) hoặc EE (6) mà sẽ trở lại trong hai bản gốc, ví dụ lớp unproxied hoặc tên của nó?

tôi cần:

com.company.employeemgmt.EmployeeManager 

Tất nhiên, tôi chỉ đơn giản là có thể sử dụng chuỗi thao tác, nhưng tôi muốn biết nếu chức năng như vậy đã là Java- (EE) -inbuilt.

Tôi đã tìm thấy java.reflect.Proxy, mà tôi có thể sử dụng để phát hiện proxy:

public static void doSomething(Class<? implements Serializable> managerClass) 
{ 
    if (Proxy.isProxyClass(managerClass)) 
    { 
     // unproxy how? 
     managerClass = managerClass.getUnproxiedClass(); 
    } 

    // delegate 
    doSomething(managerClass.getName()); 
} 


public static void doSomething(String prefix) 
{ 
    // do real work 
    ... 
} 

..., nhưng làm thế nào sẽ bạn dereference lớp ban đầu?

Cập nhật:

Bí quyết sẽ được truy cập MyUtil.doSomething(EmployeeManager.class) (hoặc MyUtil.doSomething(EmployeeManager.class.getName())), nhưng tôi muốn sử dụng/vượt qua MyUtil.doSomething(this.getClass()) (hoặc MyUtil.doSomething(this.getClass().getName())) từ tất cả các khách hàng như mã này có thể được sao chép xung quanh mà không thay đổi thủ công .

+0

Bạn đã thử managerClass.getDeclaringClass() hoặc managerClass.getEnclosingClass()? – jdb

+0

Cả hai đều trả về giá trị rỗng. – Kawu

+0

Không có gì bạn làm ở đây sẽ là di động hoặc ổn định. Proxy thực sự chỉ là "liên quan đến" lớp khác.CDI không quy định công nghệ nào được sử dụng để proxy hoặc bất kỳ cách nào để lấy từ proxy đến chi tiết Class của Managed Bean (mặc dù bạn có thể bắt đầu với BeanManager API và chuyển tiếp thay vì ngược lại từ một đối tượng) – covener

Trả lời

4

Phụ thuộc vào. Bạn có thể nhận được InvocationHandler cho một proxy sử dụng Proxy.getInvocationHandler(manager). Than ôi, InvocationHandler là một giao diện chỉ với một phương thức invoke và không có tính năng nào cho phép bạn có được một lớp đích; tất cả phụ thuộc vào việc thực hiện.

Là một ví dụ CXF khuôn khổ web servcie có Client và sử dụng một ClientProxy như một handler gọi liên kết, bạn có thể nhận được các khách hàng như vậy:

ClientProxy handler = (ClientProxy)Proxy.getInvocationHandler(proxiedObject); 
Client client = handler.getClient(); 

Để thêm sự xúc phạm đến thương tích, dường như WeldInvocationHandler mà bạn có thể sử dụng chỉ đơn giản là đại biểu các cuộc gọi đến một org.jboss.wsf.spi.invocation.InvocationHandler rằng nó lưu trữ đại biểu của mình trong một lĩnh vực tư nhân. Vì vậy, bạn cần phải làm một số phép thuật với sự phản chiếu để tìm ra lớp thực tế của đối tượng đích.

2

Vì lớp proxy kế thừa từ lớp gốc, tôi nghĩ rằng bạn có thể có được lớp gốc bằng cách nhận siêu lớp proxy.

0

Vì proxy triển khai giao diện proxy, bạn có thể sử dụng Class<?>[] Class.getInterfaces() để tìm hiểu lớp được ủy quyền.

private Class<?> findProxiedClass(Object proxiedObject) { 

    Class<?> proxiedClass = proxiedObject.getClass(); 

    if (proxiedObject instanceof Proxy) { 
     Class<?>[] ifaces = proxiedClass.getInterfaces(); 
     if (ifaces.length == 1) { 
      proxiedClass = ifaces[0]; 
     } else { 
      // We need some selection strategy here 
      // or return all of them 
      proxiedClass = ifaces[ifaces.length - 1]; 
     } 
    } 
    return proxiedClass; 
} 

thử nghiệm nó với

@Test 
public void testProxies() { 

    InvocationHandler handler = new InvocationHandler() { 
     @Override 
     public Object invoke(Object proxy, Method method, Object[] args) 
       throws Throwable { 
      return null; 
     } 
    }; 

    RandomAccess proxiedIface = (RandomAccess) Proxy.newProxyInstance(
      RandomAccess.class.getClassLoader(), 
      new Class[] { RandomAccess.class }, 
      handler); 

    Assert.assertEquals(RandomAccess.class, findProxiedClass(proxiedIface)); 
    Assert.assertEquals(Object.class, findProxiedClass(new Object())); 
}