I was writing before Groovy dynamically adds methods and properties and Spock single test At the time of the article, I didn't realize the magic of metaclass until one day I suddenly wanted to update the function directly without the construction process, that is, the legendary hot update.
I wrote it when I studied arthas before Implement Java hot update with arthas command redefine Previously, I saw that the functions demonstrated by stupid horse at the MTSC conference were similar, but they were manually triggered through the command line. If the command is invoked through the service, it is not the best choice.
Then I thought of the metaclass of Groovy, and I thought of executing the uploaded Groovy script through groovy.lang.GroovyShell, so as to meet the requirements of dynamic update to a certain extent. http://mpvideo.qpic.cn/0bc34yaacaaa6qadltm6sjqvbzwdahtaaaia.f10002.mp4? dis_ k=d1297f51601e96ccde5ef5e8dc92c284&dis_ t=1638419047&vid=wxv_ 2150263619790471169&format_ id=10002&support_ redirect=0&mmversion=false
Just do it. First write a normal version of the verification.
functional verification
I first create a class, then define an object method and simply output a number. Then, create two objects in the main method and call their test() methods respectively. In the middle, re implement the test() method through metaClass and output FunTester.
package com.funtest.groovytest import com.funtester.frame.SourceCode class HotUpdate extends SourceCode { public static void main(String[] args) { def update = new HotUpdate() update.test() HotUpdate.metaClass.test = {output("FunTester")} def update2 = new HotUpdate() update2.test() } public void test() { output(123) } }
Console output:
INFO-> main Current user: oker,Working directory:/Users/oker/IdeaProjects/funtester/,System coding format:UTF-8,system Mac OS X edition:10.16 INFO-> main ###### # # # # ####### ###### ##### ####### ###### ##### # # # ## # # # # # # # # # # # # # # # # # # # # # # #### # # # # # # #### ##### # #### ##### # # # # # # # # # # # # # # # # # ## # # # # # # # # # ##### # # # ###### ##### # ###### # # INFO-> main 123 INFO-> main FunTester Process finished with exit code 0
Script implementation
After functional verification, the road has been opened. Start writing a script now. The script content is to re implement the function of the test() method of the metaClass by scripting:
import com.funtest.groovytest.HotUpdate import com.funtester.frame.Output HotUpdate.metaClass.test = {Output.output(\"FunTester\")}
Next, I simulate the function of the server after receiving the request script (String type parameter) through groovy.lang.GroovyShell. Finally, the complete code is:
import com.funtester.frame.SourceCode import com.funtester.frame.execute.ExecuteGroovy class HotUpdate extends SourceCode { public static void main(String[] args) { def update = new HotUpdate() update.test() ExecuteGroovy.executeScript("import com.funtest.groovytest.HotUpdate\n" + "import com.funtester.frame.Output \n" + "\n" + "HotUpdate.metaClass.test = {Output.output(\"FunTester\")}") def update2 = new HotUpdate() update2.test() } public void test() { output(123) } }
Console output:
INFO-> main Current user: oker,Working directory:/Users/oker/IdeaProjects/funtester/,System coding format:UTF-8,system Mac OS X edition:10.16 INFO-> main ###### # # # # ####### ###### ##### ####### ###### ##### # # # ## # # # # # # # # # # # # # # # # # # # # # # #### # # # # # # #### ##### # #### ##### # # # # # # # # # # # # # # # # # ## # # # # # # # # # ##### # # # ###### ##### # ###### # # INFO-> main 123 INFO-> main FunTester Process finished with exit code 0
Perfect implementation. There are some problems encountered when copying scripts. Intellij will automatically treat some characters as escape characters, resulting in the difference between the executed script and the actual script, resulting in failure. It is recommended that you try to avoid this way of directly pasting copied strings and instead use the scheme of uploading script files or using ngrinder, Store the script in an accessible Git repository.