Spring Boot 中,Java反射操作(bean自动注入)
2018-11-29 本文已影响0人
不敢预言的预言家
我这里写成了一个 RequestMapping 方便调用维护,但是会有注入的风险,慎用,做好权限处理。
反射代码
/**
* 风险操作
*
* @param request
* @return
*/
@RequestMapping(value = "/risk-operator")
public Object riskOperator(@RequestBody String request) {
try {
JSONObject requestJson = JSON.parseObject(request, Feature.OrderedField);
Class[] paramClasses = null;
Object[] paramArgs = null;
JSONObject paramJson = requestJson.getJSONObject("method_param");
if (!ObjectUtils.isEmpty(paramJson)) {
paramClasses = new Class[paramJson.size()];
paramArgs = new Object[paramJson.size()];
int i = 0;
for (Map.Entry<String, Object> entry : paramJson.entrySet()) {
Class paramClass = Class.forName(entry.getKey());
paramClasses[i] = paramClass;
if (entry.getKey().startsWith("java")) {
// java基础类型参数,调用构造函数(String,Long,Double,BigDecimal...)
Constructor constructor = paramClass.getConstructor(String.class);
paramArgs[i] = constructor.newInstance(entry.getValue());
} else {
// 项目定义数据,使用工具封装一下(site.yuyanjia.template.common.model.WebUserDO)
String paramInnerJson = paramJson.getString(entry.getKey());
Object object = JSON.parseObject(paramInnerJson, paramClass);
paramArgs[i] = object;
}
i++;
}
}
Class targetClass = Class.forName(requestJson.getString("class_name"));
// 使用spring content 获取类的实例
ApplicationContext context = Application.applicationContext;
Object bean = context.getBean(targetClass);
/*
给实例化的类注入需要的bean (@Autowired)
如果不注入,被@Autowired注解的变量会报空指针
*/
context.getAutowireCapableBeanFactory().autowireBean(bean);
Method method = targetClass.getDeclaredMethod(requestJson.getString("method_name"), paramClasses);
// 设置访问权限
method.setAccessible(true);
Object result = method.invoke(bean, paramArgs);
return result;
} catch (Exception ex) {
log.error("请求内容 {},异常内容", request, ex);
return ex.toString();
}
}
ApplicationContext 直接在Spring Boot启动类获取
Application.java
@SpringBootApplication
@Slf4j
public class Application {
public static ApplicationContext applicationContext;
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
Application.applicationContext = context;
log.warn("application start done");
}
}
请求数据格式
{
"class_name": "site.yuyanjia.template.website.service.impl.UserServiceImpl",
"method_name": "test",
"method_param": {
"java.lang.String": "yuyanjia",
"java.math.BigDecimal": "1",
"site.yuyanjia.template.common.model.WebUserDO": {
"username": "yuyanjia",
"password": "mima"
}
}
}
- class_name : 目标类
- method_name : 目标方法
- method_param : 方法参数