easyopen原理解析——不到100行代码实现一个最精简的easyopen

easyopen的核心代码非常简单,底层是调用method.invoke()方法实现的。最精简的代码如下:

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * 迷你版easyopen
 *
 * @author tanghc
 */
public class MiniEasyopen {

    @Documented
    @Retention(RUNTIME)
    @Target(METHOD)
    @interface Api {
        String name() default "";
    }

    static class ApiInfo {
        private Object handler;
        private Method method;

        public ApiInfo(Object handler, Method method) {
            this.handler = handler;
            this.method = method;
        }
    }

    // 业务类
    static class GoodsService {
        // 获取商品接口
        @Api(name = "goods.get")
        public String getGoods(String param) {
            return "your param is " + param;
        }
    }

    // 存放接口信息的地方
    Map<String, ApiInfo> map = new ConcurrentHashMap<String, ApiInfo>();

    // 注册接口
    public void regist() {
        // 找到bean对象,可以从spring容器中获取
        Object[] beans = {new GoodsService()};

        for (Object bean : beans) {
            Class<?> serviceClass = bean.getClass();
            Method[] methods = serviceClass.getMethods();
            for (Method method : methods) {
                // 找到注解方法
                Api api = method.getAnnotation(Api.class);
                if (api != null) {
                    System.out.println(String.format("【注册接口%s,%s】", api.name(), method.toString()));
                    map.put(api.name(), new ApiInfo(bean, method));
                }
            }
        }

    }

    // 调用接口
    public Object invoke(String name, String param) throws Exception {
        // 根据方法名找到对应的接口信息
        ApiInfo apiInfo = map.get(name);
        if (apiInfo == null) {
            throw new IllegalAccessException("调用不存在的服务" + name);
        }
        Method method = apiInfo.method;
        Object handler = apiInfo.handler;
        return method.invoke(handler, param);
    }


    public static void main(String[] args) throws Exception {
        // 服务启动
        MiniEasyopen miniEasyopen = new MiniEasyopen();
        // 注册接口
        miniEasyopen.regist();

        // 请求名,请求参数,假设已经从request中解析出来
        String name = "goods.get";
        String param = "iphone";

        // 方法调用
        Object result = miniEasyopen.invoke(name, param);

        System.out.println("返回结果:" + result);
    }
}

从main方法开始看,服务启动做了注册接口操作,即找到被@Api标记的方法,然后保存这个方法的信息。

调用接口时,根据接口名找到方法信息,然后invoke一下,返回结果。

这个最基本的骨架搭建完之后,可以进行一些额外则操作,比如签名验证、拦截器、方法结果处理操作。

easyopen就是在此基础上逐渐完善起来的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值