关于@Adaptive注解

引用dubbo官方文档的一段话:

​ Adaptive 可注解在类或方法上。当 Adaptive 注解在类上时,Dubbo 不会为该类生成代理类。注解在方法(接口方法)上时,Dubbo 则会为该方法生成代理逻辑。Adaptive 注解在类上的情况很少,在 Dubbo 中,仅有两个类被 Adaptive 注解了,分别是 AdaptiveCompiler 和 AdaptiveExtensionFactory。此种情况,表示拓展的加载逻辑由人工编码完成。更多时候,Adaptive 是注解在接口方法上的,表示拓展的加载逻辑需由框架自动生成。

为什么要设计adaptive?注解在类上和注解在方法上的区别?

​ adaptive设计的目的是为了识别固定已知类和扩展未知类。

  1. 注解在类上:代表人工实现,实现一个装饰类(设计模式中的装饰模式),它主要作用于固定已知类,

    目前整个系统只有2个, AdaptiveCompiler,AdaptiveExtensionFactory

    • 为什么AdaptiveCompiler这个类是固定已知的?因为整个框架仅支持Javassist和JdkCompiler。
    • 为什么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类);来提取对象

一、在接口上

在接口上,在调用getAdaptiveExtension方法时,直接返回该类(不会去动态生成代理类),然后执行IOC

二、在方法上

在方法上会生成代理代理类

关于createAdaptiveExtensionClassCode方法

  1. 至少有一个方法被@Adaptive修饰

  2. 被@Adaptive修饰得方法得参数 必须满足参数中有一个是URL类型,或者有至少一个参数有一个“公共且非静态的返回URL的无参get方法”

  3. @Adaptive注解中的值这里我叫它value,value可以是一个数组,如果为空的话,vlaue等于接口名小写(例如接口名:per.qiao.A, 那么value=a)

    获取扩展名图如下

这里value表示@Adaptive注解的值(数组)中最后一个value, 如果该数组为空,则value等于接口名小写

java生成动态类的模板

java生成动态类的模板

package <扩展点接口所在包>;

public class <扩展点接口名>$Adpative implements <扩展点接口> {

  public <有@Adaptive注解的接口方法>(<方法参数>) {
if(是否有URL类型方法参数?) 使用该URL参数
else if(是否有方法类型上有URL属性) 使用该URL属性
<else 在加载扩展点生成自适应扩展点类时抛异常,即加载扩展点失败!> if(获取的URL == null) {
throw new IllegalArgumentException("url == null");
} //...获取扩展点名 图解如上 <接口> extension = (接口) ExtensionLoader.getExtensionLoader(接口).getExtension(扩展点名);
extension.<有@Adaptive注解的接口方法>(<方法参数>)
} public <无@Adaptive注解的接口方法>(<方法参数>) {
throw new UnsupportedOperationException("is not adaptive method!");
}
}

小结:

  1. 一个扩展文件内只能有一个扩展类被@Adaptive修饰,而且还需要有其他的初@Adaptive和AOP扩展之外的至少一个其他扩展

  2. @Adaptive如果方在类上,那么cachedAdaptiveClass就等于该类

    Holder cachedAdaptiveInstance就包装这该类

  3. 如果标注在方法上,那么该方法必须有参数为ulr或者参数有返回url的方法,并且会生成动态文件

@Adaptive注解的更多相关文章

  1. 03_Adaptive注解

    [Adaptive注解] package com.alibaba.dubbo.common.extension; import com.alibaba.dubbo.common.URL; import ...

  2. Dubbo源码学习之-Adaptive自适应扩展

    前言 最近三周基本处于9-10-6与9-10-7之间,忙碌的节奏机会丢失了自己.除了之前干施工的那段经历,只看参加软件开发以来,前段时间是最繁忙的了.忙的原因,不是要完成的工作量大,而是各种环境问题, ...

  3. Dubbo SPI机制之三Adaptive自适应功能

    JDK标准中SPI机制的一个问题就是其一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源:扩展点加载失败,其他扩展点都用不了了.Dubbo是如何解决该问题动态的选 ...

  4. dubbo工作原理

    part -- 外挂1.dubbo借助spring的schema启动和初始化 1.1 spring扫描所有jar下META-INF的spring.handlers和spring.schemas. 1. ...

  5. Dubbo源码分析系列---扩展点加载

    扩展点配置: 约定: 在扩展类的jar包内,放置扩展点配置文件:META-INF/dubbo/接口全限定名,内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔.(摘自dubbo文档) 示例: ...

  6. dubbo源码—SPI

    Java中的SPI SPI,Service Provider Interface,java中提供的一种使程序可扩展的方式,系统定义好接口规范,供其他服务提供方实现,服务提供方将自己jar包META-I ...

  7. Dubbo中SPI扩展机制解析

    dubbo的SPI机制类似与Java的SPI,Java的SPI会一次性的实例化所有扩展点的实现,有点显得浪费资源. dubbo的扩展机制可以方便的获取某一个想要的扩展实现,每个实现都有自己的name, ...

  8. Dubbo 源码分析 - 自适应拓展原理

    1.原理 我在上一篇文章中分析了 Dubbo 的 SPI 机制,Dubbo SPI 是 Dubbo 框架的核心.Dubbo 中的很多拓展都是通过 SPI 机制进行加载的,比如 Protocol.Clu ...

  9. Dubbo 源码分析 - SPI 机制

    1.简介 SPI 全称为 Service Provider Interface,是 Java 提供的一种服务发现机制.SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加 ...

随机推荐

  1. 怎么样使用vuex

    https://www.cnblogs.com/songrimin/p/7815850.html

  2. Asis_2016_b00ks wp

    目录 程序基本信息 程序漏洞 利用思路 exp脚本 参考 程序基本信息 程序漏洞 有一个读入函数,程序的所有输入都靠它读取,这个程序有个很明显的off_by_one漏洞,在输入时多输入一个0字符. 利 ...

  3. nodejs取参四种方法 req.body, req.params, req.param, req.body

    获取请求很中的参数是每个web后台处理的必经之路,nodejs的 express框架 提供了四种方法来实现. req.body req.query req.params req.param() 首先介 ...

  4. python笔记9 线程进程 threading多线程模块 GIL锁 multiprocessing多进程模块 同步锁Lock 队列queue IO模型

    线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...

  5. SQL-W3School-高级:SQL 数据库

    ylbtech-SQL-W3School-高级:SQL 数据库 1.返回顶部 1. 现代的 SQL 服务器构建在 RDBMS 之上. DBMS - 数据库管理系统(Database Managemen ...

  6. JavaScript的深拷贝

    javaScript的拷贝有浅拷贝和深拷贝.拷贝我们一般拷贝对象,获取对象的内容(字段.函数)都给复制一遍 浅拷贝:一般只是简单的赋值 //浅拷贝 var obj1={name:"cat&q ...

  7. 012-多线程-JUC集合-Queue-SynchronousQueue和LinkedTransferQueue

    一.SynchronousQueue概述 SynchronousQueue是一个不存储元素的队列.每一个put操作必须等待一个take操作,否则不能继续添加元素. 它支持公平访问队列.默认情况下线程采 ...

  8. 123467123456#1#-----com.twoapp.DaDiShuGame01--前拼后广--现实打地鼠游戏jiemei

    com.twoapp.DaDiShuGame01--前拼后广--现实打地鼠游戏jiemei

  9. Flask 应用如何部署

    1. Why Flask+Gunicorn+Nginx Flask+Gunicorn+Nginx是最常用的Flask部署方案,大家深究过为何用这样的搭配么? 1.1 Why? Flask 是一个web ...

  10. ubuntu18.04中将刚下载解压的eclipse添加到启动器

    在/usr/share/applications/目录下新建一个名为eclipse.desktop的文件. 文件内容如下: [Desktop Entry] Version=2018.09 Name=E ...