2009-10-23 11 views
8

Por ejemplo, si I ejecutar un script Groovy, que modifica la clase meta String, la adición de un foo método()¿Cómo deshago los cambios de metaclase después de ejecutar GroovyShell?

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

cuando creo un nuevo shell después de eso y ejecutarlo, los cambios son todavía allí

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

¿Hay alguna manera de deshacer todos los cambios de clase meta después de ejecutar GroovyShell? Probé

shell1.getClassLoader().clearCache(); 

y

shell1.resetLoadedClasses(); 

pero que no hice un cambio.

+0

¿Puedo hacer esto con un messloader de clase? – cretzel

Respuesta

11

Puede utilizar

GroovySystem.metaClassRegistry.removeMetaClass(String.class); 

a revertir todos los cambios realizados en la clase meta de cadena.

Como alternativa, solo podría cambiar la metaclase de una determinada instancia de String, por lo que no se verían afectadas todas las instancias de String.

+1

Gracias. Pero qué, si no sé qué cambios de clase meta se han hecho. Piense en una aplicación como Groovy Web Console, donde diferentes usuarios ejecutan scripts Groovy. Quiero que estos usuarios no interfieran. – cretzel

+0

Consulte mi respuesta a continuación, que resuelve su problema de no saber qué metaclases han cambiado. –

0

Me doy cuenta de que esta es una pregunta algo más antigua, pero es el primer resultado en Google cuando estaba buscando exactamente el mismo problema.

La solución que elegí fue poner groovy en un nuevo cargador de clases (utilizando plexus-classworlds), por lo que cuando finaliza el script, se descarga el cargador de clases (y se eliminan también los cambios en la metaclase).

+0

¿Tiene un ejemplo de código de esto? –

+0

@JohnMercier ¿No me ayudó mi respuesta anterior? –

2

También puedes usar MetaClassRegistryCleaner.

Antes de hacer algunos cambios MetaClass, puede hacerlo

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

Y cuando desea restablecer los cambios MetaClass al estado en que estaban antes.

Usted puede hacer

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

De esta manera se pueden cancelar todos los cambios MetaClass realizadas durante la duración.

Cuestiones relacionadas