Java 反射调用

3 篇文章 0 订阅
2 篇文章 0 订阅

Java 反射调用

1. 反射定义

是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

2.反射用途

在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。

3. RPC调用

java远程调用,服务端反序列化请求数据后,根据全路径类名、方法名、参数列表,解析并反射调用服务端接口对外提供服务。

4. Gateway的实现

为反射调用的扩展实现,不区分客户端实现方式,根据请求信息,反射处理后返回结果。

5. 示例代码

@Service
public class MethodInvokeJob implements SimpleJobProcessor {

    private static final Logger logger = LoggerFactory.getLogger(MethodInvokeJob.class);

    private static List<String> constantKeys =  Arrays.asList("boolean", "char", "int", "byte", "short", "long", "float", "double", "java.lang.String");

    private static List<String> constantValues =  Arrays.asList("java.lang.Boolean", "java.lang.Character", "java.lang.Integer", "java.lang.Byte", "java.lang.Short", "java.lang.Long", "java.lang.Float", "java.lang.Double", "java.lang.String");

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void process(JobContext context) throws Exception {
        logger.info("Start Execute Task:" + this.getClass().getSimpleName() + " -> " + context.getParameter());
        Map<String, Object> parameters = (Map<String, Object>) JSON.parse(context.getParameter());
        executeInvoke(parameters);
        logger.info("End Execute Task:" + this.getClass().getSimpleName() + " -> " + context.getParameter());

    }

    /**
     * 执行反射操作,调用指定方法
     *
     * @param parameters
     */
    private void executeInvoke(Map<String, Object> parameters) {

        String className = String.valueOf(parameters.get("className"));
        String method = String.valueOf(parameters.get("methodName"));
        Map<String, Object> params = (Map<String, Object>) JSON.parse(String.valueOf(parameters.get("param")));
        try {
            Class<?> aClass = Class.forName(className);
            Object instance = applicationContext.getBean(aClass);
            Method[] methods = Class.forName(className).getDeclaredMethods();

            Object ret = null;

            for (int i = 0; i < methods.length; i++) {
                if (method.equals(methods[i].getName()) && methods[i].getParameterCount() == params.size()) {
                    logger.info("开始执行反射操作: className {}, method {}, params {}", className, method, parameters.get("param"));
                    methods[i].setAccessible(true);
                    if (0 == params.size()){
                        ret = methods[i].invoke(instance);
                    }else {
                        List<Object> paramList = new ArrayList<>();
                        Class<?>[] paramsType = methods[i].getParameterTypes();
                        for (int j = 0; j < params.size(); j++) {
                            Object param = JSON.parseObject(String.valueOf(parameters.get("param" + j)), paramsType[j]);
                            paramList.add(param);
                        }
                        ret = methods[i].invoke(instance, paramList.toArray());
                    }
                }
                logger.info("执行反射操作完成: {}", ret);
            }
        } catch (Exception e) {
            logger.error("执行反射调用失败->{}", e);
        }
    }

    public void invoke(Map<String, Object> parameters) {

        String className = String.valueOf(parameters.get("className"));
        String method = String.valueOf(parameters.get("methodName"));
        List<Object> params = (List<Object>) JSON.parse(String.valueOf(parameters.get("param")));
        try {
            Class<?> aClass = Class.forName(className);
            Object instance = aClass.newInstance();
            Method[] methods = Class.forName(className).getDeclaredMethods();

            Object ret = null;

            for (int i = 0; i < methods.length; i++) {
                if (method.equals(methods[i].getName()) && methods[i].getParameterCount() == params.size()) {
                    logger.info("开始执行反射操作: className {}, method {}, params {}", className, method, parameters.get("param"));
                    methods[i].setAccessible(true);
                    if (0 == params.size()){
                        ret = methods[i].invoke(instance);
                    }else {
                        List<Object> paramList = new ArrayList<>();
                        Class<?>[] paramsType = methods[i].getParameterTypes();
                        for (int j = 0; j < paramsType.length; j++) {
                            if (constantKeys.contains(paramsType[j].getName())){
                                int index = constantKeys.indexOf(paramsType[j].getName());
                                String decodeType = constantValues.get(index);
                                Class<?> clazz = Class.forName(decodeType);
                                paramList.add(clazz.cast(params.get(j)));
                            }else {
                                paramList.add(JSON.parseObject(String.valueOf(params.get(j)), Class.forName(paramsType[j].getName())));
                            }
                        }
                        methods[i].invoke(instance, paramList.toArray());
                    }
                }
                logger.info("执行反射操作完成");
            }
        } catch (Exception e) {
            logger.error("执行反射调用失败->{}", e);
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值