重要概念介绍:
1.proxyFactory:就是为了获取一个接口的代理类,例如获取一个远程接口的代理。 它有2个方法,代表2个作用 a.getInvoker:针对server端,将服务对象,如DemoServiceImpl包装成一个Invoker对象。 b.getProxy :针对client端,创建接口的代理对象,例如DemoService的接口。 2.Wrapper:它类似spring的BeanWrapper,它就是包装了一个接口或一个类,可以通过wrapper对实例对象进行赋值 取值以及制定方法的调用。 3.Invoker:它是一个可执行的对象,能够根据方法的名称、参数得到相应的执行结果。 它里面有一个很重要的方法 Result invoke(Invocation invocation), Invocation是包含了需要执行的方法和参数等重要信息,目前它只有2个实现类RpcInvocation MockInvocation 它有3种类型的Invoker 1.本地执行类的Invoker server端:要执行 demoService.sayHello,就通过InjvmExporter来进行反射执行demoService.sayHello就可以了。 2.远程通信类的Invoker client端:要执行 demoService.sayHello,它封装了DubboInvoker进行远程通信,发送要执行的接口给server端。 server端:采用了AbstractProxyInvoker执行了DemoServiceImpl.sayHello,然后将执行结果返回发送给client. 3.多个远程通信执行类的Invoker聚合成集群版的Invoker client端:要执行 demoService.sayHello,就要通过AbstractClusterInvoker来进行负载均衡,DubboInvoker进行远程通信,发送要执行的接口给server端。 server端:采用了AbstractProxyInvoker执行了DemoServiceImpl.sayHello,然后将执行结果返回发送给client. 4.Protocol 1.export:暴露远程服务(用于服务端),就是将proxyFactory.getInvoker创建的代理类 invoker对象,通过协议暴露给外部。 2.refer:引用远程服务(用于客户端), 通过proxyFactory.getProxy来创建远程的动态代理类,例如DemoService的远程动态接口。 5.exporter:维护invoder的生命周期。 6.exchanger:信息交换层,封装请求响应模式,同步转异步。 7.transporter:网络传输层,用来抽象netty和mina的统一接口。 8.Directory:目录服务 StaticDirectory:静态目录服务,他的Invoker是固定的。 RegistryDirectory:注册目录服务,他的Invoker集合数据来源于zk注册中心的,他实现了NotifyListener接口,并且实现回调notify(List<URL> urls), 整个过程有一个重要的map变量,methodInvokerMap(它是数据的来源;同时也是notify的重要操作对象,重点是写操作。)
dubbo-spi:
为什么要设计adaptive?注解在类上和注解在方法上的区别? adaptive设计的目的是为了识别固定已知类和扩展未知类。 1.注解在类上:代表人工实现,实现一个装饰类(设计模式中的装饰模式),它主要作用于固定已知类, 目前整个系统只有2个,AdaptiveCompiler、AdaptiveExtensionFactory。 a.为什么AdaptiveCompiler这个类是固定已知的?因为整个框架仅支持Javassist和JdkCompiler。 b.为什么AdaptiveExtensionFactory这个类是固定已知的?因为整个框架仅支持2个objFactory,一个是spi,另一个是spring 2.注解在方法上:代表自动生成和编译一个动态的Adpative类,它主要是用于SPI,因为spi的类是不固定、未知的扩展类,所以设计了动态$Adaptive类. 例如 Protocol的spi类有 injvm dubbo registry filter listener等等 很多扩展未知类, 它设计了Protocol$Adaptive的类,通过ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(spi类);来提取对象 为什么dubbo要自己设计一套SPI? 这是原始JDK spi的代码 ServiceLoader<Command> serviceLoader=ServiceLoader.load(Command.class); for(Command command:serviceLoader){ command.execute(); } dubbo在原来的基础上设计了以下功能 1.原始JDK spi不支持缓存;dubbo设计了缓存对象:spi的key与value 缓存在 cachedInstances对象里面,它是一个ConcurrentMap 2.原始JDK spi不支持默认值,dubbo设计默认值:@SPI("dubbo") 代表默认的spi对象,例如Protocol的@SPI("dubbo")就是 DubboProtocol, 通过 ExtensionLoader.getExtensionLoader(Protocol.class).getDefaultExtension()那默认对象 3.jdk要用for循环判断对象,dubbo设计getExtension灵活方便,动态获取spi对象, 例如 ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(spi的key)来提取对象 4.原始JDK spi不支持 AOP功能,dubbo设计增加了AOP功能,在cachedWrapperClasses,在原始spi类,包装了XxxxFilterWrapper XxxxListenerWrapper 5.原始JDK spi不支持 IOC功能,dubbo设计增加了IOC,通过构造函数注入,代码为:wrapperClass.getConstructor(type).newInstance(instance), dubbo spi 的目的:获取一个指定实现类的对象。 途径:ExtensionLoader.getExtension(String name) 实现路径: getExtensionLoader(Class<T> type) 就是为该接口new 一个ExtensionLoader,然后缓存起来。 getAdaptiveExtension() 获取一个扩展类,如果@Adaptive注解在类上就是一个装饰类;如果注解在方法上就是一个动态代理类,例如Protocol$Adaptive对象。 getExtension(String name) 获取一个指定对象。 -----------------------ExtensionLoader.getExtensionLoader(Class<T> type) ExtensionLoader.getExtensionLoader(Container.class) -->this.type = type; -->objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); -->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() -->this.type = type; -->objectFactory =null; 执行以上代码完成了2个属性的初始化 1.每个一个ExtensionLoader都包含了2个值 type 和