反射之随心所欲的方法调用

人生很短,愿你能胸襟开阔,去容纳山海贫瘠,去挥霍青涩蹉跎,去寄托岁月巍峨,去尽情耗尽所有的爱恨枯竭。

场景描述

  • 在进行接口调试的时候,一般都会使用Postman进行接口调用调试,即直接填上请求路径,请求参数,然后点击直接对后台发起请求,后台对代码进行一个调试,简单方便。
  • 在有对外提供请求接口的情况下当然好用,但是,在很多情况下方法并不会对外提供接口,他只是给上游提供请求服务,并不需要在Controller层对外暴露接口。
  • 就比如一个付款流程,客户进行一个订单支付操作,订单服务会调用库存服务进行一个扣库存的操作,假如这时候要调试一个库存扣减不正确的问题,于是我们每次都要发起支付调用订单服务接口,订单服务又请求库存服务在进行一个代码断点调试,如此反复,烦之又烦…
  • 你可以在库存服务开发一个Controller对外接口,单独对库存接口进行调试,很棒,至少不走那套支付流程和调用订单服务了,但也很蠢,为了调试接口直接写个对外的方法,实在麻烦,如果忘记删除这段代码上了生产,可想而知有多危险!
  • 那该如何处理呢?这时候就可以用到反射了。

需求分析

  • 首先我们需要对外开放一个请求接口,这个接口具备通用性,就是说直接调用该接口,经过反射之后可以达到后台调用不同方法的目的。
  • 思考一下,我们后台要调用方法,首先要有调用方,以及要调用的方法,还有请求参数。所以,对于这个通用测试接口,我们需要有的参数是:调用对象,对象调用的方法,方法请求参数封装类以及该类的参数。

实战分析

  1. 一般情况下,方法调用方都是Spring Bean对象,而获取Bean就可以使用ApplicationContext通过Bean的name获得,所以第一个参数(方法调用方)只要传BeanName即可。
  2. 然后要获取该类某个方法的请求参数类,我们只能通过请求参数类全路径获取该类Class类型,所以第二个参数(方法的请求参数类)需要传入类的全路径名。
  3. 第一步获得了对象就可以通过 对象.getClass() 的方式获取到该对象的类的Class类型,根据Class类型的getMethod(方法名称, 方法请求参数类型),就能够获取到要调用的Method,这里缺少第三个参数方法名称,也需要前端传入。
  4. 第二步只是获取到请求参数的类类型,但是真正的请求参数却还没有放进该类里边,所以需要前端传入第四个参数,即方法调用的实际参数。
  5. 最后一步就是方法的调用,第三步得到的Method调用invoke()方法进行执行。

代码示例

  • 通用调试接口
    @RequestMapping(value = "/system/operation", method = RequestMethod.POST)
    public Object operation(@RequestBody DubboProxyRequest request) throws Exception{
		// 注意只能在非生产环境调用哦
		if(environmentHelper.isProductionEnvironment()){
			return null;
		}
		// 获取调用的bean对象
        Object invokedFacade = context.getBean(request.getFacadeName());
		// 获取请求参数Class类
        Class actualRequestClass = Class.forName(request.getActualRequestClassName());
        // 获取要调用的方法
        Method invokedMethod = invokedFacade.getClass().getMethod(request.getMethodName(), actualRequestClass);
		// 封装请求参数到请求参数类中
        Object actualRequest = JSON.parseObject(JSON.toJSONString(request.getActualRequestData()), actualRequestClass);
        // 方法的执行
        return invokedMethod.invoke(invokedFacade, actualRequest);
    }
  • 通用调试接口的请求参数 DubboProxyRequest
@Data
public class DubboProxyRequest extends BaseRequest {
    /**
     * BeanName
     */
    @NotBlank
    private String facadeName;
    /**
     * 要调用的方法
     */
    @NotBlank
    private String methodName;
    /**
     * 请求参数全路径名
     */
    @NotBlank
    private String actualRequestClassName;
    /**
     * 实际请求参数
     */
    @NotBlank
    private Map actualRequestData;
}

总结

  • 通过上述通用接口,根据传入参数的变化,可以达到调用后台不同方法的目的,从而进行一个很方便的调试。
  • 假如客户请求是一个很长的调用链,而要调试某个调用节点的时候,只需要针对该节点(即方法)传入其所需参数进行调试就行了,如此一想,反射真是太强大和灵活了
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发飙的蜗牛咻咻咻~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值