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就是在此基础上逐渐完善起来的。

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

相关推荐