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