美文网首页
Spring Boot 中,Java反射操作(bean自动注入)

Spring Boot 中,Java反射操作(bean自动注入)

作者: 不敢预言的预言家 | 来源:发表于2018-11-29 17:56 被阅读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 : 方法参数

    相关文章

      网友评论

          本文标题:Spring Boot 中,Java反射操作(bean自动注入)

          本文链接:https://www.haomeiwen.com/subject/qwgfcqtx.html