2012-04-18 9 views
11

Sto scrivendo un motore di gioco/libreria in cui dispongo di una classe dispatcher di eventi che invia eventi chiamando metodi listener di classi di gestori eventi "registrati". Si può registrare un gestore di eventi/listener con il dispatcher di eventi chiamando il metodo di dispatcher appropriato.Aggiunta di codice a una classe Java con Strumentazione: ASM o BCEL?

Questo ovviamente porta ad alcuni codici di codice per la registrazione di ogni gestore di eventi (e anche altri aspetti del mio motore hanno un codice bolierplate simile), quindi mi chiedevo: che ne dici di usare semplicemente Instrumentation per aggiungere tutto il codice necessario durante il caricamento della classe del gestore di eventi, in modo che non sia necessaria alcuna registrazione esplicita con il dispatcher di eventi durante la codifica: la chiamata al metodo di registrazione del dispatcher viene aggiunta automaticamente quando viene eseguito il programma.

Sono a conoscenza del fatto che per poter utilizzare Instrumentation si dovrebbe utilizzare qualche API di modifica bytecode. Ne conosco due: ASM e BCEL. Quale dovrei usare? Ovviamente, questo è un compito piuttosto semplice che sto cercando di fare, quindi voglio quello che è più facile da imparare e meglio documentato.

MODIFICA: ecco un esempio specifico.

originale classe gestore di eventi:

@Handler //indicates this this class should be transformed 
public class MouseEventHandler implements EventHandler<MouseEvent> 
{ 
    //hidden default constructor 
    public void handleEvent(MouseEvent event) 
    { ... } 
} 

Dopo la trasformazione:

@Handler 
public class MouseEventHandler implements EventHandler<MouseEvent> 
{ 
    public MouseEventHandler() 
    { 
     //add this line of code to default constructor 
     Game.getEventDispatcher().addEventHandler(this); 
    } 
    public void handleEvent(MouseEvent event) 
    { ... } 
} 

risposta

20

Tuttavia, prenderei in considerazione altre opzioni prima di passare alla manipolazione del bytecode.

+0

bcel è stato incluso in JDK –

+1

@ alexander.box: Sì, come dipendenza dal trasformatore XSLTC Xalan, ma è API non standard e anche nascosto nel pacchetto com.sun.org.apache.bcel.internal ! Meglio fornire il tuo barattolo. – Daniel

+2

Oh, e anche se ci sono: ASM è un'ottima scelta quando le classi devono essere strumentate. Facile da capire e da usare. Inoltre ha una documentazione molto bella. – Daniel

6

Aggiungere la logica a poche classi potrebbe essere noioso, ma a meno che tu non abbia migliaia di gestori, questo è il modo in cui andrei. Rendilo semplice.

Detto,

Game.registerHandler(this); 

sarebbe più orientato agli oggetti.

Un'alternativa all'aggiunta della logica in ogni classe consiste nell'introdurre uno factory che è responsabile dell'istanza dei gestori.

HandlerFactory.createMouseHandler(); 

e il metodo createMouseHandler contiene qualcosa come

Handler mh = new MousheHandler(); 
registerHandler(mh); 
return mh; 

Se non si desidera una di queste opzioni, vorrei prendere in considerazione sia un quadro aspetto (forse AspectJ) o un contenitore per Invertion di controllo (forse IoC primaverile). Gli aspetti ti permettono di annotare la tua fonte e "tessere" il codice nei luoghi selezionati. Un contenitore IoC consente di controllare il ciclo di vita dell'oggetto (ad es. Istanziazione). Entrambi usano la strumentazione bytecode dietro la scena.

Ma se si desidera eseguire da soli la strumentazione , posso solo confrontare Javassist e ASM che ho utilizzato personalmente.

ASM è di basso livello e funziona davvero a livello di codice byte java. Devi averne familiarità. La struttura è molto ben progettata, il manuale è eccellente ed è un'ottima libreria. Da un lato, può essere complicato sostituire i pattern del bytecode, perché richiede una cosiddetta trasformazione "stateful". Dall'altro lato, hai il pieno controllo sul bytecode.

Javassist è più di alto livello. Non operi al livello grezzo di bytecode, un livello leggermente più alto, ad es. campi di lettura/scrittura, invio di messaggi, costruttori. Inoltre, consente di specificare le modifiche utilizzando la normale sintassi java, che viene quindi compilata dal framework. L'API è un po 'confusa, perché il progetto è cresciuto nel corso degli anni. C'è una documentazione sul framework, ma non così centralizzata come con ASM.