在执行GroovyShell之后,如何撤消元类更改?
例如,如果我执行一个Groovy脚本,该脚本修改字符串元类,添加一个方法foo() 当我在此之后创建一个新的shell并执行它时,更改仍然存在在执行GroovyShell之后,如何撤消元类更改?,groovy,metaprogramming,Groovy,Metaprogramming,例如,如果我执行一个Groovy脚本,该脚本修改字符串元类,添加一个方法foo() 当我在此之后创建一个新的shell并执行它时,更改仍然存在 GroovyShell shell2 = new GroovyShell(); Object result = shell2.evaluate("'a'.foo()"); 在执行GroovyShell之后,有没有办法撤消所有元类更改?我试过了 shell1.getClassLoader().clearCache(); 及 但这并没有改变。您可以使用
GroovyShell shell2 = new GroovyShell();
Object result = shell2.evaluate("'a'.foo()");
在执行GroovyShell之后,有没有办法撤消所有元类更改?我试过了
shell1.getClassLoader().clearCache();
及
但这并没有改变。您可以使用
GroovySystem.metaClassRegistry.removeMetaClass(String.class);
还原对字符串元类所做的所有更改
或者,您只能更改某个字符串实例的元类,因此并非所有字符串实例都会受到影响。我意识到这是一个比较老的问题,但这是我在Google上搜索完全相同问题时的第一个结果
我选择的解决方案是将groovy放入一个新的类加载器(通过使用plexus classworlds),这样当脚本完成时,类加载器就会被释放(因此对元类的任何更改也会被释放)。您也可以使用MetaClassRegistryCleaner 在进行元类更改之前,您可以
MetaClassRegistryCleaner registryCleaner = MetaClassRegistryCleaner.createAndRegister()
GroovySystem.metaClassRegistry.addMetaClassRegistryChangeEventListener(registryCleaner)
当您想要将元类更改重置为之前的状态时
你能行
registryCleaner.clean()
GroovySystem.metaClassRegistry.removeMetaClassRegistryChangeEventListener(registryCleaner)
通过这种方式,您可以重置在此期间所做的所有元类更改。谢谢。但是,如果我不知道已经做了哪些元类更改,又会怎样呢。想象一下GroovyWeb控制台这样的应用程序,不同的用户在其中执行Groovy脚本。我希望这些用户不要干预。请参阅下面的我的答案,它解决了您不知道哪些元类已更改的问题。我可以通过一些类加载器混乱来做到这一点吗?@JohnMercier没有我上面的答案的帮助吗?在许多方面,这是一种比注册表清理更好的方法,尤其是允许并发执行。
MetaClassRegistryCleaner registryCleaner = MetaClassRegistryCleaner.createAndRegister()
GroovySystem.metaClassRegistry.addMetaClassRegistryChangeEventListener(registryCleaner)
registryCleaner.clean()
GroovySystem.metaClassRegistry.removeMetaClassRegistryChangeEventListener(registryCleaner)