关于利用java反射实现简单的动态java调用

从上周开始,就一直在捣鼓java反射。自己在试着封装一些动态调用java方法的构件。但是总是不是那么如意。一方面,对java反射机制不是那么理解。另一方面,只是为了得到一个公共的java反射方法,然后各种网上找资料。这里,感谢各位网友提供的关于java反射的说明以及代码。这里,要感谢博客园的这篇文章,让我解决了数组反射的问题:Java 反射 Array动态创建数组。
下面,先贴一段之前的反射方法:

  protected static HashMap DynamicInvokedSimple(
        HashMap datas, HashMap dynamicInvoke)
        throws Exception {
    HashMap ret = new HashMap();

    if (dynamicInvoke != null && dynamicInvoke.size() > 0) {
        String logicPath = (String) dynamicInvoke
                .get(CommonUtils.DYNAMIC_LOGICPATH);
        String logicType = (String) dynamicInvoke
                .get(CommonUtils.DYNAMIC_LOGICTYPE);
        HashMap paramsMap = (HashMap) dynamicInvoke
                .get(CommonUtils.DYNAMIC_PARAMJSON);

        if (logicPath == null || "".equals(logicPath)) {
            throw new Exception("logicPath不能为空!");
        }

        if (logicType == null || "".equals(logicType)) {
            throw new Exception("logicType不能为空!");
        }

        String classPath = logicPath.substring(0,
                logicPath.lastIndexOf("."));
        String methodName = logicPath
                .substring(logicPath.lastIndexOf(".") + 1);
        Object c;
        try {
            c = Class.forName(classPath).newInstance();
        } catch (Exception e) {
            throw new Exception("创建" + classPath + "实例失败!");
        }

        Object[] paramObjs = new Object[2];
        paramObjs[0] = datas;
        paramObjs[1] = paramsMap;

        try {
            ret = (HashMap) (c.getClass().getMethod(methodName,
                    new Class[] { HashMap.class, HashMap.class }).invoke(c,
                    paramObjs));
            return ret;
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("执行" + methodName + "失败!");
        }
    }
    ret.put(CommonUtils.RETCODE, CommonUtils.SUCCESS);
    return ret;
}

先说说这个方法,这个方法第一个参数表示的是传入的参数信息,第二个参数里包含的是反射的java信息,包括java的方法路径,java方法中部分参数信息。

但是这个方法有点局限性。

  1. 需要反射调用的方法必须带有两个Map参数;
  2. 需要反射调用的方法必须返回Map。

在这样的基础上,我决定重新完善下,希望能够得到一个可以定义任意个数参数,任意类型参数,任意返回值类型的方法,并通过java反射机制调用。于是,重新整理下,代码如下:

    protected Map DynamicInvokedSimple(
        List datas, HashMap dynamicInvoke)
        throws Exception {
    Map ret = new HashMap();

    if (dynamicInvoke != null && dynamicInvoke.size() > 0) {
        String logicPath = (String) dynamicInvoke
                .get(CommonUtils.DYNAMIC_LOGICPATH);
        String logicType = (String) dynamicInvoke
                .get(CommonUtils.DYNAMIC_LOGICTYPE);
        HashMap paramsMap = (HashMap) dynamicInvoke
                .get(CommonUtils.DYNAMIC_PARAMJSON);

        if (logicPath == null || "".equals(logicPath)) {
            throw new Exception("logicPath不能为空!");
        }

        if (logicType == null || "".equals(logicType)) {
            throw new Exception("logicType不能为空!");
        }

        String classPath = logicPath.substring(0,
                logicPath.lastIndexOf("."));
        String methodName = logicPath
                .substring(logicPath.lastIndexOf(".") + 1);
        Object c;
        try {
            c = Class.forName(classPath).newInstance();
        } catch (Exception e) {
            throw new Exception("创建" + classPath + "实例失败!");
        }
        try {
            
            Method[] methods = c.getClass().getDeclaredMethods();  // 获取方法名
            Method methodInfo = null;                              // 定义方法
            for (int i = 0; i < methods.length; i++) {
                Method method = methods[i];
                
                /**
                 * 表示一定是有重载方法,那么不仅需要名字匹配,还需要参数个数匹配
                 */
                if (null != dynamicInvoke.get(paramsCountName)) {
                    int methodCount = method.getParameterCount();
                    int paramCount = Integer.parseInt(dynamicInvoke.get(paramsCountName).toString().substring(0,dynamicInvoke.get(paramsCountName).toString().contains(".")?
                            dynamicInvoke.get(paramsCountName).toString().indexOf("."):dynamicInvoke.get(paramsCountName).toString().length()));
                    if (paramCount==methodCount && methodName.equals(method.getName())) {
                        methodInfo = method;
                        break;
                    }
                }else{
                
                    /**
                     * 表示一般的方法
                     */
                    if(methodName.equals(method.getName())){
                        methodInfo = method;
                        break;
                    }
                }
            }
            
            if (null == methodInfo) {
                ret.put(CommonUtils.RETCODE, CommonUtils.FAILURE);
                ret.put(CommonUtils.RETMSG, PARAMSFAILURE+"或"+METHODFAILURE);
                return ret;
            }
            
            /**
             * 获取参数类型
             */
            Class[] types = methodInfo.getParameterTypes();
            Class[] args = new Class[methodInfo.getParameterCount()];
            Object[] paramObjs = new Object[methodInfo.getParameterCount()];
            
            if(null != paramsMap){
                paramObjs[paramObjs.length-1] = paramsMap;
            }
            
            
            if(datas.size() > 0){
                for (int i = 0; i < datas.size(); i++) {
                    paramObjs[i] = datas.get(i);
                }
            }
            
            for (int i = 0; i < paramObjs.length; i++) {
                if (null == paramObjs[i]) {
                    System.out.println(types[i].getName());
                    System.out.println(types[i].getSimpleName());
                    if ("Map".equals(types[i].getSimpleName())) {
                        paramObjs[i] = new HashMap<>();
                    }else if ("List".equals(types[i].getSimpleName())) {
                        paramObjs[i] = new ArrayList<>();
                    }else if ("Set".equals(types[i].getSimpleName())) {
                        paramObjs[i] = new HashSet<>();
                    }else{
                        try {
                            /**
                             * 判断是不是数组
                             */
                            if (Class.forName(types[i].getName()).isArray()) {
                                /**
                                 * 是数组的处理方法
                                 */
                                Class theClass = getClass(types[i].getName());
                                paramObjs[i] = Array.newInstance(theClass, 0);
                            }else{
                                /**
                                 * 如果不是数组的处理方法
                                 */
                                boolean bool = true;
                                for (int j = 0; j < getBasicType().size(); j++) {
                                    String key = getBasicType().get(j);
                                    if (types[i].getName().equals(key)) {
                                        bool = false;
                                        break;
                                    }
                                    
                                }
                                if (bool) {
                                    paramObjs[i] = Class.forName(types[i].getName()).newInstance();
                                }else{
                                    paramObjs[i] = getBasicType(types[i].getName());
                                }
                            }
                            
                        } catch (InstantiationException e) {
                            paramObjs[i] = Class.forName(types[i].getName());
                        } catch (ClassNotFoundException e) {
                            paramObjs[i] = getBasicType(types[i].getName());
                        }
                    }
                }
                
            }
            
            for (int i = 0; i < args.length; i++) {
                args[i] = types[i];
            }
            
            /**
             * 判断方法是否有返回值
             */
            if ("void".equals(methodInfo.getReturnType().getName())) {
                c.getClass().getMethod(methodName,args
                        ).invoke(c,
                        paramObjs);
                ret.put(CommonUtils.RETCODE, CommonUtils.SUCCESS);
                ret.put(CommonUtils.RETMSG, SUCCESS);
                return ret;
            }
            ret.put("data",(c.getClass().getMethod(methodName,args
                    ).invoke(c,
                    paramObjs)));
            ret.put(CommonUtils.RETCODE, CommonUtils.SUCCESS);
            ret.put(CommonUtils.RETMSG, SUCCESS);
            return ret;
        } catch (Exception e) {
            ret.put(CommonUtils.RETCODE, CommonUtils.SUCCESS);
            ret.put(CommonUtils.RETMSG, SUCCESS);
            e.printStackTrace();
            throw new Exception("执行" + methodName + "失败!");
        }
    }
    //ret.put(CommonUtils.RETCODE, CommonUtils.SUCCESS);
    return ret;
}

/**
 * 字节型(byte),短整型(short),整型(int),长整型(long),字符型(char),浮点型(float),双精度型(double),布尔型(boolean)
 * @return
 */
private List getBasicType(){
    List list = new ArrayList();
    list.add("int");
    list.add("byte");
    list.add("short");
    list.add("long");
    list.add("char");
    list.add("float");
    list.add("double");
    list.add("boolean");
    list.add("java.lang.Integer");
    list.add("java.lang.Byte");
    list.add("java.lang.Short");
    list.add("java.lang.Long");
    list.add("java.lang.Character");
    list.add("java.lang.Float");
    list.add("java.lang.Double");
    list.add("java.lang.Boolean");
    return list; 
}

private Object getBasicType(String key){
    if ("int".equals(key)) {
        return 0;
    }else if ("boolean".equals(key)) {
        return false;
    }else if ("byte".equals(key)) {
        return (byte)0;
    }else if ("short".equals(key)) {
        return (short)0;
    }else if ("long".equals(key)) {
        return 0;
    }else if ("char".equals(key)) {
        return (char)0;
    }else if ("float".equals(key)) {
        return 0;
    }else if ("double".equals(key)) {
        return 0;
    }else if ("java.lang.Integer".equals(key)) {
        return new Integer(0);
    }else if ("java.lang.Byte".equals(key)) {
        return new Byte("0");
    }else if ("java.lang.Short".equals(key)) {
        return new Short((short) 0);
    }else if ("java.lang.Long".equals(key)) {
        return new Long(0);
    }else if ("java.lang.Character".equals(key)) {
        return new Character('0');
    }else if ("java.lang.Float".equals(key)) {
        return new Float(0);
    }else if ("java.lang.Double".equals(key)) {
        return new Double(0);
    }else if ("java.lang.Boolean".equals(key)) {
        return new Boolean(false);
    }
    return null;
}


private Class getClass(String className) throws ClassNotFoundException{
      if(className.contains("int")) return int.class;
      if(className.contains("long")) return long.class;
      if(className.contains("boolean")) return boolean.class;
      if(className.contains("byte")) return byte.class;
      if(className.contains("short")) return short.class;
      if(className.contains("char")) return char.class;
      if(className.contains("float")) return float.class;
      if(className.contains("double")) return double.class;
      if(className.contains("String")) return String.class;
      return Class.forName(className);
}
 
 

我把第一个参数变成一个list了。也就是,无论多少个参数的方法,都可以通过这个方法的反射去实现。如果本来有5个参数,但是用户只传了3个参数,其他剩余的参数,我将直接赋为初始值。在自己处理的过程中,比较麻烦的是基础数据类型和接口。比如,Map的接口有很多,如何根据传入的参数是Map类型,我要怎么去找到他的实现类来初始化值呢。一般需要初始化值的,是因为用户在传入参数的过程中,没有传入。
我在处理Map这样的jdk中自带的集合的时候,我这里也是直接就根据接口创建为它的实现类hashMap了 。还有基本数据类型,我以为可以通过反射里的某个方法,来初始化,最后,我还是创建了一个集合来存放这些基础信息,再通过传入的数据类型进行匹配。
另一个比较麻烦的就是数组,在反射中,数组的创建和对象实例化还有些不同。还好,最终通过网上提供的资料,终于搞定了这个问题。
一个类里可能出现方法的重载,这个时候通过方法反射的时候,就不知道具体该调用哪个方法了。所以,我在传参的过程中,多加了一个控制参数个数的方法,因为重载的方法,参数个数是不同的,但方法名是相同的。最后这个问题算是解决了。
当然,写这个方法的过程中,还有很多数据类型没有考虑到,比如枚举,注解什么的。要彻底理解反射的原理,可能还需要一段时间。总之,这个方法,现在一般的java方法可以通过反射机制动态调用了。
如果有写的不对的地方,希望大家帮我纠正一下。感激不尽。

你可能感兴趣的:(关于利用java反射实现简单的动态java调用)