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"
    }
  }
}
上一篇下一篇

猜你喜欢

热点阅读