自己实现Dubbo Invoker

1.Dubbo Invoker 用来执行spring注入的业务接口的实现类的方法。下面我来自己实现一套。基本上是dubbo的设计模式思想。

2.先看下使用说明:

//User 对象
class User {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
// 业务 user接口
interface IUserSerice {
    public User login(User user);
}
// 接口实现
class UserServiceImpl implements IUserSerice {
    @Override
    public User login(User user) {
        System.err.println(user.getName() + " login....");
        user.setName("login success");
        return user;
    }
}
 public static void main(String[] args) {
         // 模仿spring new 业务对象
        IUserSerice userSerice = new UserServiceImpl();
        User user = new User();
        user.setName("hadluo");
        // 用构造 IUserSerice 接口 对应的 Invoker ,dubbo是extensionloader构造的,这里我们直接模拟.
        Invoker<IUserSerice> invoker = JavassistProxyFactory.getInvoker(userSerice, IUserSerice.class);
        //构造调用方法信息,Invocation是调用方法信息,我们这里是 login方法信息
        Invocation invocation = new NativeInvocation("login",new Class<?>[]{User.class},new Object[]{user}) ;
        //执行一次 本地调用
        Result result = invoker.invoker(invocation);
        System.err.println("返回 值:" + ((User)result.getResult()).getName());
    }
//###########结果
hadluo login....
返回值:login success
  1. 实现细节

JavassistProxyFactory
用来构造Invoker(执行器) , dubbo是 用ExtensionLoader来构造JavassistProxyFactory 的,ExtensionLoader的实现 见另一篇: https://blog.csdn.net/luozheng4698729/article/details/80070630

public class JavassistProxyFactory {
    // proxy: UserServiceImpl实例对象 , type: IUserService接口的class
    public static <T> Invoker<T> getInvoker(T proxy, Class<?> type) {
        // Wrapperd 是对 IUserService接口 的包装操作,后面会细讲
        final Wrapper wrapper = Wrapper.getWrapper(type);
        return new AbstractProxyInvoker<T>(type, proxy) {
            @Override
            public Object doInvoke(Object proxy, Invocation invocation) throws Throwable {
                return wrapper.invokeMethod(proxy, invocation.getMethodName(),
                        invocation.getParameterTypes(), invocation.getArguments());
            }
        };
    }
 }

Invoker
执行器 接口

public interface Invoker<T>{
    // 执行方法, Invocation 为执行信息(包括执行 哪个方法,参数等信息),Result为执行结果
    Result invoker(Invocation invocation);
    // 省略其它 dubbo中的方法
}

Invocation
执行 方法信息 ,dubbo里面包括本地 方法执行 信息类型和 RPC方法执行信息类型。

/***
 * 执行 方法信息 (参数,返回值,方法名)
 * 
 * @author HadLuo
 * @since JDK1.7
 * @history 2018年4月27日 新建
 */
public interface Invocation {
    // 获取执行的方法名称
    String getMethodName();
    // 获取方法 参数 类型
    Class<?>[] getParameterTypes();
    //获取方法 参数
    Object[] getArguments();
}
// 本地 方法执行 信息类型, 我们就写一个
public class NativeInvocation implements Invocation {
    private String methodName;
    private Class<?>[] parameterTypes;
    private Object[] arguments;
    public NativeInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments) {
        super();
        this.methodName = methodName;
        this.parameterTypes = parameterTypes;
        this.arguments = arguments;
    }
    @Override
    public String getMethodName() {
        return methodName;
    }
    @Override
    public Class<?>[] getParameterTypes() {
        return parameterTypes;
    }
    @Override
    public Object[] getArguments() {
        return arguments;
    }
}

Result
执行器Invoker 的执行结果,与Invocation对应,包括本地执行结果,rpc执行结果

/***
 * 执行器Invoker 的执行结果
 * 
 * @author HadLuo
 * @since JDK1.7
 * @history 2018年4月27日 新建
 */
public interface Result {
    public Object getResult();
}
// 这里 我们 就写 一个 本地执行结果
public class RpcResult implements Result {
    private Object object;

    public RpcResult(Object object) {
        this.object = object;
    }
    @Override
    public Object getResult() {
        return object;
    }
}

AbstractProxyInvoker
执行器实现,很重要

/***
 * 抽象 代理 执行 器
 * 
 * @author HadLuo
 * @since JDK1.7
 * @history 2018年4月27日 新建
 */
public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
    // spring注入的业务对象,也就是上面的 UserServiceImpl对象
    private final T object;

    public AbstractProxyInvoker(Class<?> type, T object) {
        this.object = object;
    }

    /***
     * 抽象 执行方法 ,交给 Wrapper实现
     * 
     * @param proxy
     * @param invocation
     * @return
     * @throws Throwable
     * @author HadLuo 2018年4月27日 新建
     */
    public abstract Object doInvoke(Object proxy, Invocation invocation) throws Throwable;

    @Override
    public Result invoker(Invocation invocation) {
        if (invocation instanceof NativeInvocation) {
            try {
                // 间接调用 doInvoke 方法
                return new RpcResult(doInvoke(object, invocation));
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        if(invocation instanceof RpcInvocation){
            // 远程调用, 这里先不管
        }
        throw new RuntimeException("暂时 只 实现  本地的 调用");
    }
}

Wrapper
Wrapper是一个独立的抽象类, 用来 包装对接口class的操作(上面我们说的IUserService)。这里对class操作,我们可以抽象几种操作:
1.获取class中所有字段的名称 : abstract public String[] getPropertyNames();

2.根据字段名称获取字段类型:abstract public Class getPropertyType(String pn);

3.判断class中是否存在某字段:abstract public boolean hasProperty(String name);

4.获取class对象的某字段的值:abstract public Object getPropertyValue(Object instance, String pn) throws Throwable;

5.设置字段的值:abstract public void setPropertyValue(Object instance, String pn, Object pv) throws Throwable;

6.执行方法:abstract public Object invokeMethod(Object instance, String methodName, Class[] types, Object[] args) throws Throwable;

很明显第6条才是最重要的。实现原理就是动态构造一个Wrapper的实现类Wrapper0来实现上述6个抽象方法的 , 下面我们看下怎么实现这些方法的:

public abstract class Wrapper {
    //动态类名称,Wrapper0 的 0  调一次 就加1, 依次是:Wrapper0,Wrapper1,Wrapper2...
    private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0);
    // 缓存, key: IUserService接口class, value: 动态类
    private static ConcurrentHashMap<Class<?>, Wrapper> WRAPPERS = new ConcurrentHashMap<Class<?>, Wrapper>();

    public static Wrapper getWrapper(Class<?> type) {
        Wrapper wrapper = WRAPPERS.get(type);
        if (wrapper == null) {
            // 动态实现类
            wrapper = makeWrapper(type);
            //加入缓存
            WRAPPERS.putIfAbsent(type, wrapper);
        }
        return wrapper;
    }

    abstract public String[] getPropertyNames();

    abstract public Class<?> getPropertyType(String pn);

    abstract public boolean hasProperty(String name);

    abstract public Object getPropertyValue(Object instance, String pn) throws Throwable;

    abstract public void setPropertyValue(Object instance, String pn, Object pv) throws Throwable;

    abstract public Object invokeMethod(Object instance, String methodName, Class<?>[] types, Object[] args) throws Throwable;

    private static Wrapper makeWrapper(Class<?> type) {
        //这个 ClassGenerator 是dubbo写的动态类构造工具,使用javassist底层实现,工具我放在文章最后
        ClassGenerator classGenerator = ClassGenerator.newInstance(Wrapper.class.getClassLoader());
        // extends Wrapper.class
        classGenerator.setSuperClass(Wrapper.class);
        // class 名称
        classGenerator.setClassName(Wrapper.class.getName() + WRAPPER_CLASS_COUNTER.getAndIncrement() + "$");

        // public static Map<String, Class<?>> pts; // key: 属性名称 value:属性类型
        classGenerator.addField("public static " + Map.class.getName() + " pts;");
        // 属性名称 集合
        classGenerator.addField("public static String[] pNames;");

        // getPropertyNames 抽象方法实现
        classGenerator.addMethod("public String[] getPropertyNames(){return pNames;}");
        // getPropertyType 抽象方法实现
        classGenerator.addMethod("public Class getPropertyType(String pName) { return (Class)pts.get(pName); }");
        // hasProperty 抽象方法实现
        classGenerator
                .addMethod("public boolean hasProperty(String name){  return pts.containsKey(name) ; }");
        // getPropertyValue 抽象方法实现
        classGenerator
                .addMethod("public Object getPropertyValue(Object instance, String pName) throws Throwable { "
                        + "try {"
                        + "java.lang.Class clazz = instance.getClass();"
                        + "java.lang.reflect.Field f = clazz.getDeclaredField(pName);"
                        + "return f.get(instance);" + "} catch (Exception e) {throw e;} }");
        // setPropertyValue 抽象方法实现
        classGenerator
                .addMethod("public void setPropertyValue(Object instance, String pName, Object pValue) throws Throwable {"
                        + "try {"
                        + "java.lang.reflect.Field f = instance.getClass().getDeclaredField(pName);"
                        + "f.set(instance, pValue);" + "} catch (Exception e) { throw e;}}");
        // invokeMethod 抽象方法实现
        classGenerator
                .addMethod("public Object invokeMethod(Object instance, String methodName, Class[] types, Object[] args) throws Throwable {"
                        + "try {"
                        + "java.lang.Class clazz = instance.getClass();"
                        + "java.lang.reflect.Method method = clazz.getDeclaredMethod(methodName, types);"
                        + "if (method == null) { throw new NullPointerException(\"没有 在 \" + clazz.getName() + \" 中 找到 方法: \" + methodName);}"
                        + "return method.invoke(instance, args);" + "} catch (Exception e) {throw e;}}");

        try {
            Class<?> proxyClass = classGenerator.toClass();
            if (proxyClass == null) {
                throw new RuntimeException("生成动态类型错误");
            }
            Map<String, Class<?>> pts = new HashMap<String, Class<?>>();
            for (Field f : type.getDeclaredFields()) {
                pts.put(f.getName(), f.getType());
            }
         // 跟动态类 的静态字段设置值
            proxyClass.getDeclaredField("pts").set(null, pts);
            proxyClass.getDeclaredField("pNames").set(null, pts.keySet().toArray(new String[0]));

            return (Wrapper) proxyClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

上述动态构造类的代码不必深究,其实就是构造如下类(实现也很简单):

// 生成的动态类==============
class Wrapper0 extends Wrapper {
    // key: 属性名称 value:属性类型
    public static Map<String, Class<?>> pts;
    // 属性名称
    public static String[] pNames;
    @Override
    public Object invokeMethod(Object instance, String methodName, Class<?>[] types, Object[] args)
            throws Throwable {
        try {
            java.lang.Class clazz = instance.getClass();
            java.lang.reflect.Method method = clazz.getDeclaredMethod(methodName, types);
            if (method == null) {
                throw new NullPointerException("没有 在 " + clazz.getName() + " 中 找到 方法: " + methodName);
            }
            return method.invoke(instance, args);
        } catch (Exception e) {
            throw e;
        }
    }
    @Override
    public String[] getPropertyNames() {
        return pNames;
    }

    @Override
    public Class<?> getPropertyType(String pName) {
        return pts.get(pName);
    }

    @Override
    public boolean hasProperty(String name) {
        return pts.containsKey(name);
    }

    @Override
    public Object getPropertyValue(Object instance, String pName) throws Throwable {
        try {
            java.lang.Class clazz = instance.getClass();
            java.lang.reflect.Field f = clazz.getDeclaredField(pName);
            return f.get(instance);
        } catch (Exception e) {
            throw e;
        }
    }
    @Override
    public void setPropertyValue(Object instance, String pName, Object pValue) throws Throwable {
        try {
            java.lang.reflect.Field f = instance.getClass().getDeclaredField(pName);
            f.set(instance, pValue);
        } catch (Exception e) {
            throw e;
        }
    }
}

上述就是所有实现细节,跟Dubbo肯定有点差异,不必较真,主要是思想一致。要工程源码加我: 657455400 csdn下载链接:https://download.csdn.net/download/luozheng4698729/10379503

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值