方法出参自动赋值

1.技术点
反射,泛型,Object,递归

2.参考源码

/**
 * Created by jeremy.liang on 2018/9/3.
 */
public class SetterUtils {
    public static boolean isJavaClass(Class<?> clz) {
        //校验类加载器的原理可以细化探究下
        return clz != null && clz.getClassLoader() == null;
    }
 
 
    public static Object testReturnSetMethod(Class clz) throws Exception {
 
        //根据名字反射得到object并且实例化,被赋值的object实例
        Class<?> objectClz = Class.forName(clz.getName());
        Object object = objectClz.newInstance();
 
        //遍历所有方法
        for(Method method: object.getClass().getMethods())
        {
            //只操作相应的的setter方法
            if(!method.getName().startsWith("set"))
            {
                continue;
            }
 
            //params - 方法参数List,argArray-参数初值
            Parameter[] params = method.getParameters();
            Object[] argArray = new Object[params.length];
 
            int i = 0;
 
            //理论上我们的方法只有一个参数要赋值
            for(Parameter para :method.getParameters())
            {
                Class type = para.getType();
                //判断参数是否是yoghurt自定义的类型,若是则递归创建内层object实例,若不是则所有是基本类型,直接区分类型设初值就可
                if(isJavaClass(para.getType()))
                {
                    if (type.toString().endsWith("String")) {
                        Object tempObj = new String("testString");
                        argArray[i++] = tempObj;
                    }else if(type.toString().endsWith("int") || type.toString().endsWith("Integer")){
                        Object tempObj = new Integer(222);
                        argArray[i++] = tempObj;
                    }else if(type.toString().endsWith("byte") || type.toString().endsWith("Byte")){
                        Object tempObj = new Byte((byte)1);
                        argArray[i++] = tempObj;
                    }else if(type.toString().endsWith("BigDecimal") ){
                        BigDecimal tempBig = BigDecimal.valueOf(1.11);
                        Object tempObj =tempBig;
                        argArray[i++] = tempObj;
                    }else if(type.toString().endsWith("List")) {
                        //得到泛型参数类型的方法,可以重点了解下ParameterizedType(继承Type接口)
                        ParameterizedType parameterizedType = (ParameterizedType) para.getParameterizedType();
                        //得到泛型<>内的类型,也同样需要是否自定义类的判断并且赋初值
                        Type typeInOne = parameterizedType.getActualTypeArguments()[0];
                        if(isJavaClass((Class)typeInOne))
                        {
                            Object tempObj2Lst = new Object();
                            if (typeInOne.toString().endsWith("String")) {
                                tempObj2Lst = new String("ListString");
                            }else if(typeInOne.toString().endsWith("int") || typeInOne.toString().endsWith("Integer")){
                                tempObj2Lst = new Integer(333);
                            }else if(typeInOne.toString().endsWith("byte") || typeInOne.toString().endsWith("Byte")) {
                                tempObj2Lst = new Byte((byte) 1);
                            }
                            else if(type.toString().endsWith("BigDecimal") ) {
                                BigDecimal tempBig = BigDecimal.valueOf(1.11);
                                Object tempObj =tempBig;
                                argArray[i++] = tempObj;
                            }
                            else
                            {
                                //TODO 其他数据结构如Map等
                            }
                            List<Object> tempLists = new ArrayList<>();
                            tempLists.add(tempObj2Lst);
                            argArray[i++] = tempLists;
                        }
                        else
                        {
                            List<Object> tempLists = new ArrayList<>();
                            Object tempObj = testReturnSetMethod((Class)typeInOne);
                            tempLists.add(tempObj);
                            argArray[i++] = tempLists;
                        }
 
                    }else {
                        //TODO 其他数据结构如Map等
                    }
 
                }
                else
                {
                    //若方法入参为自定义类型,只需要递归创建实例并赋值返回接口
                    Object tempObj = testReturnSetMethod(type);
                    argArray[i++] = tempObj;
 
                }
            }
            //调用相应setter method实例化即可,并且传入符合的初始化参数,否则报methodNofound方法
            method.invoke(object,argArray);
            System.out.println(object);
 
        }
 
        return object;
    }
}

3.总结
一开始走了一段弯路,思路是:先遍历VO的所有field,得到name/type,判断了name的类型之后,再构造setName的方法,然后再关联其setField的方法,在处理自动装箱等这些方法不好操作,
由于 反射获取方法不支持自动装箱或拆箱,那反射调用方法支持自动装箱或拆箱,并且处理List<>的泛型类参数时候有点绕,其实也可以做到->已实现

但是后来参考了一些网上的思想,再去看了看RPC的实现方法,其实没必要检测Field,对于我的需求来说,我只需要把所有setter方法遍历一遍,然后invoke一次,就能得到效果,并不需要两层转化等关系~~思路更加清晰且容易实现

4.类似swagger、代码迁移脚本,xml配置读取,大致也是按照这些思路

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值