2013-06-23 17 views
10

Chciałbym utworzyć program podklasowy. Chyba mam kilka opcji - Javassist, CGLib, BCEL lub ASM.Java - tworzenie podklasy dynamicznie

W przypadku użycia jedna aplikacja jest zorientowana na klasę, a rozszerzenia są oparte na klasach. Dlatego nie mogę mieć jednej klasy jako bazy dla wielu rozszerzeń sterowanych przez zewnętrzne skrypty.

Teraz - jak to zrobić? Znalazłem przykłady z przechwytywaniem wywołań metod, dostępu do pola, inicjalizacji itp. Ale nic o podklasowaniu.

Chciałbym skończyć z klasy, które:

  • ma imię, które chcę.
  • jest (bezpośrednie, w najlepszym wypadku) podklasę danej klasy
  • kopiuje konstruktora (ów) z klasy nadrzędnej (lub zwraca super(...))
  • końcu, chciałbym dać mu jakieś adnotacje.

Wiem, że jest to możliwe, ponieważ różne integracje języków dynamicznych, takie jak GroovyClassLoader, mogą to zrobić.

Odpowiedz

5

Jest to dość łatwe Javassist: zależność

import javassist.CannotCompileException; 
import javassist.ClassPool; 
import javassist.CtClass; 
import javassist.NotFoundException; 

static Class<? extends DefinitionBasedMigrator> createClass(String fullName) 
     throws NotFoundException, CannotCompileException 
{ 
    ClassPool pool = ClassPool.getDefault(); 

    // Create the class. 
    CtClass subClass = pool.makeClass(fullName); 
    final CtClass superClass = pool.get(DefinitionBasedMigrator.class.getName()); 
    subClass.setSuperclass(superClass); 
    subClass.setModifiers(Modifier.PUBLIC); 

    // Add a constructor which will call super(...); 
    CtClass[] params = new CtClass[]{ 
     pool.get(MigratorDefinition.class.getName()), 
     pool.get(GlobalConfiguration.class.getName()) 
    }; 
    final CtConstructor ctor = CtNewConstructor.make(params, null, CtNewConstructor.PASS_PARAMS, null, null, subClass); 
    subClass.addConstructor(ctor); 

    return subClass.toClass(); 
} 

Maven:

<!-- https://mvnrepository.com/artifact/org.javassist/javassist --> 
<dependency> 
    <groupId>org.javassist</groupId> 
    <artifactId>javassist</artifactId> 
    <version>3.22.0-GA</version> 
</dependency> 
2

Java Prokura może być w stanie zrobić to, czego potrzebują - są zasadniczo pozwalają na dynamiczne warstwy funkcjonalność na szczycie obiekt, ponieważ możesz przechwycić wszystkie wywołania metod do tego obiektu i albo obsłużyć je samodzielnie, albo wywołać wywołania metod do klasy bazowej. W zależności od tego, co chcesz zrobić, możliwe, że uzyskasz taki sam wynik, jak utworzenie dynamicznej podklasy. Oracle ma na swojej stronie internetowej (adres URL odnosi się do wersji Java 1.4.2, ale nie sądzę, że zachowanie to zmieniło się w nowszych wersjach). Oto more concise example, który daje dobry aromat tego, jak wygląda kod proxy.

Możliwe jest również robienie rzeczy przy użyciu bezpośredniego kodu bajtowego (obsługiwanego przez ASM framework) jednak wyobrażam sobie, że używanie serwerów proxy byłoby prostszym podejściem.

+0

Właściwie najpierw spojrzałem na proxy, ale opuściłem to ze względu na złożoność. Javassist jest tak łatwiejszy. Ponadto serwery proxy potrzebują interfejsu i nie mogą być dalej zastępowane jako normalne klasy ... w każdym razie +1 –

7

Można skorzystać z jednej biblioteki, której szczególnie lubię; Bytebuddy.

Przykład wzięty bezpośrednio ze strony docelowej:

Class<?> dynamicType = new ByteBuddy() 
    .subclass(Object.class) 
    .method(ElementMatchers.named("toString")) 
    .intercept(FixedValue.value("Hello World!")) 
    .make() 
    .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) 
    .getLoaded(); 

Jest niezwykle elastyczny i na pewno warto sprawdzić, jeśli chcesz, aby utrzymać włosy, Osobiście wybrać ciężki wykorzystanie javassist można uzyskać dość brzydki i niechlujny czasami, bytebuddy czuje się jak dobrze potrzebny powiew świeżego powietrza!

Rafael Winterhalter jest również aktywny w StackOverflow, dzięki czemu można dowiedzieć się wszystkiego, co nie jest pewne.

Edytuj: moje przeprosiny za Necroposting.Wylądowałem tutaj, gdy znajomy połączył to pytanie i zapomniał sprawdzić datę.

Powiązane problemy