Introducing scripting capabilities into our applications can greatly improve flexibility. Our core development work can focus on the development of core platform capabilities. The functions of specific scenarios can be implemented through scripts. For example, Jenkins can use Groovy scripts are used to write pipelines, which can flexibly customize the build process. Spring itself provides a mechanism for groovy integration, which is divided into two ways. One is to use groovy to develop programs, which is similar to developing with java and needs to be compiled. One is to execute groovy as a script without compilation. What we introduce here is the second way, using groovy as a script.
There are two main ideas for integrating groovy scripts in spring. One is to define beans in groovy scripts, so that groovy scripts are integrated into the entire spring system. There is no difference using normal beans. One is to call the groovy script in the program and make the groovy script an executable component. Below we introduce these two methods respectively. There are two ways to declare beans defined in groovy scripts in spring, one is the traditional xml, and the other is the groovy declaration method introduced in spring-framework-4.
First we define an interface:
public interface MyService { String fun(MyDomain myDomain); }
Here provides an idea, we can use java code to write the default interface implementation, If the default implementation does not meet the requirements of a specific scenario, cooperate with the strategy mode and use groovy scripts to implement specific scenarios. The program will become very flexible. With the hot loading mechanism of the script, when the processing logic needs to change, during the running of the program, We can adjust the script content at any time and it will take effect in a timely manner.
Implement this interface in the groovy script MyServiceImpl.groovy
:
class MyServiceImpl implements MyService { @Autowired FunBean useBean; String myProp; String fun(MyDomain myDomain) { return myDomain.toString() + useBean.getFunName() + myProp; } }
The following describes how to declare beans through two configuration methods: xml and groovy.
Declaring beans through xml configuration is a traditional spring method. This method has recently been replaced by declaring through java code. But it is still the easiest way to declare beans defined in groovy scripts.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lang="http://www.springframework.org/schema/lang" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/lang https://www.springframework.org/schema/lang/spring-lang.xsd"> <lang:groovy id="myServiceXml" script-source="classpath:MyServiceImpl.groovy" refresh-check-delay="10000" > <lang:property name="myProp" value=" this is xml init prop" /> </lang:groovy> </beans>
The above xml code declares the bean myServiceXml, and script-source
specifies that the source of this bean is the script file classpath:MyServiceImpl.groovy
. Replace classpath with file to specify a script file in any location. refresh-check-delay
Defines the refresh interval of the script. When the content of the script changes, the content of the script can be automatically refreshed. lang:property
This tag can initialize and assign values to the properties of the bean.
We use xml and groovy to declare beans in two ways to assign different initial values to the myProp attribute, which can be seen in the subsequent demonstration code.
The groovy method of declaring beans was introduced in spring-framework-4. We use groovy to declare the bean myServiceGroovy. Compared with Compared to xml, groovy's declaration method is more readable.
For detailed introduction, see spring's official blog post: Groovy Bean Configuration in Spring Framework 4
import org.springframework.scripting.groovy.GroovyScriptFactory import org.springframework.scripting.support.ScriptFactoryPostProcessor beans { scriptFactoryPostProcessor(ScriptFactoryPostProcessor) { defaultRefreshCheckDelay = 10000 } myServiceGroovy(GroovyScriptFactory, 'classpath:MyServiceImpl.groovy') { bean -> bean.scope = "prototype" myProp = ' this is Bean Builder init prop' bean.beanDefinition.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, 6000) } }
GroovyScriptFactory
You can specify the location of the groovy script that defines the bean. Through the lambda expression of bean
, the properties of the bean can be assigned. In addition to the myProp property we defined, the scope and script refresh time can also be defined.
Earlier we declared 2 beans through xml and groovy: myServiceXml
and myServiceGroovy
, below we call these two beans in the program.
@SpringBootApplication @ImportResource({"classpath:xml-bean-config.xml", "classpath:BeanBuilder.groovy"}) public class Application implements CommandLineRunner { @Autowired private MyService myServiceXml; @Autowired private MyService myServiceGroovy; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) throws ScriptException, ResourceException, IllegalAccessException, InstantiationException { MyDomain myDomain = new MyDomain(); myDomain.setName("test"); System.out.println(myServiceXml.fun(myDomain)); myDomain.setName("test2"); System.out.println(myServiceGroovy.fun(myDomain)); } }
First we introduce the bean declaration file through @ImportResource
, and then the ordinary bean dependency injection and method invocation. You can see that in the use of beans, the script-defined beans There is no difference between beans written in programs. In the run method, we called the fun methods of the two beans myServiceXml and myServiceGroovy respectively. Executing the run method can see the output to the result:
MyDomain(name=test)FunBean this is xml init prop MyDomain(name=test2)FunBean this is Bean Builder init prop
In addition to the previously mentioned implementation of beans in groovy, we can also execute it through the GroovyScriptEngine provided by groovy Groovy script, this method does not depend on springframework and can also be used in ordinary java programs.
@Component public class MyEngine { private final GroovyScriptEngine engine; @Autowired private FunBean funBean; public MyEngine() throws IOException { engine = new GroovyScriptEngine(ResourceUtils.getFile("classpath:scripts/").getAbsolutePath() , this.getClass().getClassLoader()); } public void runScript(int x, int y) throws IllegalAccessException, InstantiationException, ResourceException, ScriptException { Class<GroovyObject> calcClass = engine.loadScriptByName("CalcScript.groovy"); GroovyObject calc = calcClass.newInstance(); Object result = calc.invokeMethod("calcSum", new Object[]{x, y}); System.out.println("Result of CalcScript.calcSum() method is " + result); Binding binding = new Binding(); binding.setVariable("arg", "test"); binding.setVariable("funBean", funBean); Object result1 = engine.run("CalcScript.groovy", binding); System.out.println("Result of CalcScript.groovy is " + result1); } }
First we initialize GroovyScriptEngine and pass in the path to the script file in the construction method.
There are two ways to execute a script. One is to obtain the GroovyObject and execute a method in the script through invokeMethod. The parameters of the method are passed in through the Object array.
Class<GroovyObject> calcClass = engine.loadScriptByName("CalcScript.groovy"); GroovyObject calc = calcClass.newInstance(); Object result = calc.invokeMethod("calcSum", new Object[]{x, y});
The second is to run the groovy script directly, and you can pass variables to the groovy script through Binding.
Binding binding = new Binding(); binding.setVariable("arg", "test"); binding.setVariable("funBean", funBean); Object result1 = engine.run("CalcScript.groovy", binding);
The above is the detailed content of How to integrate springboot with groovy script. For more information, please follow other related articles on the PHP Chinese website!