- 利用Groovy脚本将字符串文本转换成Class对象
- 获取Class对象中的方法
- 组装mvc请求映射信息RequestMappingInfo
- 动态将接口注入spring中
利用Groovy脚本动态生成对象
1.引入Groovy maven依赖
org.codehaus.groovy
groovy-all
2.4.7
2.测试代码
import groovy.lang.GroovyClassLoader;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
public class TestGroovy {
public static void main(String[] args) throws Exception {
//groovy提供了一种将字符串文本代码直接转换成Java Class对象的功能
GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
Class clazz = groovyClassLoader.parseClass("package com;\n" +
"\n" +
"public class Hello {\n" +
" \n" +
" public void sayHello(){\n" +
" System.out.println(\"hello\");\n" +
" }\n" +
"}");
// 创建对象
Object obj = clazz.newInstance();
// 获取方法
Method method = clazz.getDeclaredMethod("sayHello");
// 调用方法
method.invoke(obj);
}
}
执行结果为:
hello
Process finished with exit code 0
使用Spring针对反射提供的工具类:ReflectionUtils
在类型clazz上,查询name方法,参数类型列表为paramTypes;
Method findMethod(Class> clazz, String name, Class>… paramTypes)
示例代码:
import groovy.lang.GroovyClassLoader;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
public class TestReflectionUtils {
public static void main(String[] args) throws Exception {
//groovy提供了一种将字符串文本代码直接转换成Java Class对象的功能
GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
Class clazz = groovyClassLoader.parseClass("package com;\n" +
"\n" +
"public class Hello {\n" +
"\n" +
" public void sayHello(){\n" +
" System.out.println(\"无参方法\");\n" +
" }\n" +
"\n" +
" public void sayHello(String name){\n" +
" System.out.println(\"含参数方法:\" + name);\n" +
" }\n" +
"}");
// 创建对象
Object obj = clazz.newInstance();
// 无参方法
Method method = ReflectionUtils.findMethod(clazz, "sayHello");
// 含参方法
Method paramMethod = ReflectionUtils.findMethod(clazz, "sayHello", String.class);
// 调用方法
ReflectionUtils.invokeMethod(method,obj);
ReflectionUtils.invokeMethod(paramMethod,obj,"world");
}
}
执行结果为:
无参方法
含参数方法:world
Process finished with exit code 0
RequestMappingInfo
的主要作用就是用来对应封装一个控制方法的@RequestMapping
注解信息,该注解信息是综合了控制器方法以及控制器类上的@RequestMapping
等注解属性而合成的一个信息对象
主要包含以下条件:
1.PatternsRequestCondition 请求属性
2.RequestMethodsRequestCondition 请求方法
3.ParamsRequestCondition ”参数“条件
4.HeadersRequestCondition ”headers“条件
5.ConsumesRequestCondition 请求内容
6.ProducesRequestCondition 应答内容
主要使用 PatternsRequestCondition和RequestMethodsRequestCondition,使用全参构造创建对象:
// 请求路径
PatternsRequestCondition patterns = new PatternsRequestCondition("test/api");
// 请求方法
RequestMethodsRequestCondition method = new RequestMethodsRequestCondition(RequestMethod.GET);
// 创建mvc请求映射信息
RequestMappingInfo requestMappingInfo = new RequestMappingInfo(patterns, method, null,
null, null, null, null);
RequestMappingHandlerMapping 实现了接口InitializingBean,在bean加载完成后会自动调用afterPropertiesSet方法,在此方法中调用了initHandlerMethods()来实现初始化,
处理逻辑大致是使用RequestMappingInfo信息,注册到MappingRegistry中
RequestMappingHandlerMapping:
发布接口:registerMapping(RequestMappingInfo mapping, Object handler, Method method)
requestMappingHandlerMapping.registerMapping(requestMappingInfo, clazz.newInstance(), method);
下线接口:unregisterMapping(T mapping)
requestMappingHandlerMapping.unregisterMapping(requestMappingInfo);
示例代码:
import groovy.lang.GroovyClassLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
@Component
public class TestMappingRegistry {
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
public void mappingRegistry() throws Exception {
//groovy提供了一种将字符串文本代码直接转换成Java Class对象的功能
GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
Class clazz = groovyClassLoader.parseClass("package com;\n" +
"\n" +
"import org.apache.ibatis.annotations.Param;\n" +
"import org.springframework.stereotype.Controller;\n" +
"import org.springframework.web.bind.annotation.RequestParam;\n" +
"import org.springframework.web.bind.annotation.ResponseBody;\n" +
"\n" +
"@Controller\n" +
"public class Hello {\n" +
"\n" +
" public String sayHello(){\n" +
" return \"hello\";\n" +
" }\n" +
"\n" +
" @ResponseBody\n" +
" public String sayHello(@RequestParam(\"msg\") String msg){\n" +
" return \"hello \" + msg;\n" +
" }\n" +
"}");
// 无参方法
Method method = ReflectionUtils.findMethod(clazz, "sayHello");
// 含参方法
Method paramMethod = ReflectionUtils.findMethod(clazz, "sayHello", String.class);
// 请求路径
PatternsRequestCondition patterns = new PatternsRequestCondition("/test/api");
// 请求方法
RequestMethodsRequestCondition requestMethod = new RequestMethodsRequestCondition(RequestMethod.GET);
// 创建mvc请求映射信息
RequestMappingInfo requestMappingInfo = new RequestMappingInfo(patterns, requestMethod, null,
null, null, null, null);
// 发布接口(含参方法)
requestMappingHandlerMapping.registerMapping(requestMappingInfo, clazz.newInstance(), paramMethod);
}
}
调用 "/test/api" 接口:
至此动态接口发布成功!
注意事项:发布的接口不受spring管理,无法使用切面、@Autowired注解等!!!