2009-10-23 9 views
8

Ad esempio, se eseguire uno script Groovy, che modifica la Metaclasse String, aggiungendo un metodo foo()Come annullare le modifiche alla metadase dopo l'esecuzione di GroovyShell?

GroovyShell shell1 = new GroovyShell(); 
shell1.evaluate("String.metaClass.foo = {-> delegate.toUpperCase()}"); 

quando si crea una nuova shell e dopo che eseguirlo, i cambiamenti sono ancora lì

GroovyShell shell2 = new GroovyShell(); 
Object result = shell2.evaluate("'a'.foo()"); 

C'è un modo per annullare tutte le modifiche della metadata dopo l'esecuzione di GroovyShell? Ho provato

shell1.getClassLoader().clearCache(); 

e

shell1.resetLoadedClasses(); 

ma che non ha fatto un cambiamento.

+0

Posso farlo con alcuni problemi di caricamento del classloader? – cretzel

risposta

11

È possibile utilizzare

GroovySystem.metaClassRegistry.removeMetaClass(String.class); 

per ripristinare tutte le modifiche apportate alla meta classe String.

In alternativa è possibile modificare solo la meta class di una determinata istanza String, quindi non tutte le istanze di String saranno interessate.

+1

Grazie. Ma cosa, se non so quali cambiamenti di meta class sono stati fatti. Pensa a un'applicazione come Groovy Web Console, in cui diversi utenti eseguono script Groovy. Voglio che questi utenti non interferiscano. – cretzel

+0

Vedere la mia risposta qui sotto, che risolve il problema di non sapere quali metaclassi sono cambiati. –

0

Mi rendo conto che questa è una domanda un po 'più vecchia, ma è il primo risultato su Google quando cercavo esattamente lo stesso problema.

La soluzione che ho scelto era mettere scanalato in un nuovo classloader (utilizzando plesso-classworlds), in modo che quando lo script è terminato, il classloader è disposto (e quindi eventuali modifiche al metaclasse sono disposti).

+0

Hai un esempio di codice di questo? –

+0

@JohnMercier non ha risposto alla mia risposta sopra? –

2

È possibile utilizzare anche MetaClassRegistryCleaner.

Prima di fare alcuni cambiamenti metaclasse, si può fare

MetaClassRegistryCleaner registryCleaner = MetaClassRegistryCleaner.createAndRegister() 
GroovySystem.metaClassRegistry.addMetaClassRegistryChangeEventListener(registryCleaner) 

E quando si desidera ripristinare le modifiche metaclasse allo stato in cui erano prima.

Si può fare

registryCleaner.clean() 
GroovySystem.metaClassRegistry.removeMetaClassRegistryChangeEventListener(registryCleaner) 

In questo modo è possibile ripristinare tutte le modifiche apportate durante metaclasse la durata.

Problemi correlati