2009-10-20 27 views
6

Yani, bu cevabı "Zor olduğunu" muhtemelen farkındayım ama:Java: çalışma zamanında yeni uygulama türü oluşturulsun mu?

Garip fikrim var ve bu Java gibi bir yöntem oluşturmak mümkün olmadığını merak:

<T> T wrapInterface (Class<T> interfaceClass, T wrappedObject) { 
    if (mClass.isInterface()) { 
    //create a new implementation of interfaceClass that, in each method, 
    //does some action before delegating to wrappedObject 
    return thatImplementation; 
    } 
} 

Temel olarak, eğer benim arayüzüm Foo bir metod foo() tanımladıysa, bu yöntemin böyle bir şeye benzeyen yeni bir sınıf oluşturmasını isterim, bu sınıfın bir örneğini constructor parametresi olarak wrappedObject ile yarattım ve daha sonra :

( ) Gözden geçirmenin sadece aramayı kaydetmekten daha karmaşık olduğunu düşünüyorum, ancak kayıt için fikir yeterlidir. Bunu çok sayıda arayüz türü ile yapmak istiyorum, bu yüzden tüm GeneratedClasses'ı elle yazmam.

Ekstra dilbilimsel özellikler (AspectJ veya bu satırlar boyunca bir şeyler getirme) gerektirmeyen bir çözümün bonus puanları ve bu yalnızca standart JDK kitaplıklarıyla mümkün olduğunda çifte bonus puanları.

(ı kesin, Derlenebilir cevabı gerekmez;. Bunu yapmama izin verecek vb aletler/kütüphanelerin sağ setleri/sadece bir işaretçi)

teşekkürler!

+0

Yansıma ekstra dil özelliktir. –

+0

[Dinamik proxy sınıfları] 'na bakmak isteyebilirsiniz (http://docs.oracle.com/javase/7/docs/technotes/guides/reflection/proxy.html). –

cevap

3

Burada çok basit bir uygulama (ne yapmak istediğinize göre yeterince iyi değil, ama biraz düzeltmelerle ... Bakmanız gereken en önemli şey, sınıf yükleyici sorunları olurdu, o zaman bazı doğrulama sorunları olabilir, vb. .) Test amaçları için kodu kullanıyorum, bu yüzden tam olarak kaliteli ürünler değil.

@SuppressWarnings("unchecked") 
    public static <T> T generateProxy(Object realObject, Class<?>... interfaces) { 
     return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), interfaces, new SimpleInvocationHandler(realObject)); 
    } 


    private static class SimpleInvocationHandler implements InvocationHandler { 
     private Object invokee; 

     public SimpleInvocationHandler(Object invokee) { 
      this.invokee = invokee; 
     } 

     public Object invoke(Object proxy, Method method, Object[] args) 
       throws Throwable { 
      method = invokee.getClass().getMethod(method.getName(), method.getParameterTypes()); 
      if (!method.isAccessible()) { 
       method.setAccessible(true); 
      } 
      try { 
       return method.invoke(invokee, args); 
      } catch (InvocationTargetException e) { 
       throw e.getTargetException(); 
      } 
     } 
    } 
+0

Cevap için teşekkürler (ve örnek kod)! – Sbodd

1

İhtiyacınız olan şey ASM. asm-Guide.pdf kaynaktan

:
2.2.3 Yaratma sınıfları
sadece gerekli bileşeni, bir sınıf oluşturmak için ClassWriter bileşenidir. Bunu göstermek için bir örnek verelim. Altı yöntem ClassVisitor çağrıları ile oluşturulabilir

package pkg; 
public interface Comparable extends Mesurable { 
    int LESS = -1; 
    int EQUAL = 0; 
    int GREATER = 1; 
    int compareTo(Object o); 
} 

: aşağıdaki arayüz düşünün (java.lang.Class` `de dahil olmak üzere)

ClassWriter cw = new ClassWriter(0); 
cw.visit(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, 
    "pkg/Comparable", null, "java/lang/Object", 
    new String[] { "pkg/Mesurable" }); 
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "LESS", "I", 
    null, new Integer(-1)).visitEnd(); 
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "EQUAL", "I", 
    null, new Integer(0)).visitEnd(); 
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "GREATER", "I", 
    null, new Integer(1)).visitEnd(); 
cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "compareTo", 
    "(Ljava/lang/Object;)I", null, null).visitEnd(); 
cw.visitEnd(); 
byte[] b = cw.toByteArray(); 
İlgili konular