关于Dubbo扩展点加载机制(1)

Dubbo 扩展点加载机制中最关键的类是ExtensionLoader.java ,该类中持有扩展点加载的全量缓存和扩展点自有缓存。本章旨在解剖ExtensionLoader的结构和功能,机制及其他会在后续章节给出。

静态属性: private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS //保存了 扩展点接口与扩展点加载器对象的键值对

private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES // 存储了 扩展点实现的class类型 和 扩张点的实例

私有属性 private final Class<?> type; //在构造函数中赋值,存放扩展点接口class类型

private final ExtensionFactory objectFactory; //用来存放ExtensionFactory 的扩展点实现或nulll (当class等于ExtensionFactory.class时 objectFactory = null ,当class不等于ExtensionFactory.class时 objectFactory =AdaptiveExtensionFactory)

private volatile Class<?> cachedAdaptiveClass //自适应扩展点实现类,每个扩展点只会有一个 ;当扩展点实现类存在 @Adaptive 注解 或自动生成一个

private final ConcurrentMap<String, Holder<Object>> cachedInstances //spi配置文件中key 和所对应的key所对应的class全路径名

private String cachedDefaultName //spi注解中带有的默认值

方法列表: 私有构造方法 private ExtensionLoader(Class<?> type) //给属性type 赋值扩展点接口类型,objectFactory 值有两种情况,详见私有属性objectFactory

public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) //根据扩展点接口类型从EXTENSION_LOADERS中获取该扩展点的扩展点加载类;当EXTENSION_LOADERS中不存在时使用上面介绍的私有构造方法新建ExtensionLoader对象。

public T getAdaptiveExtension() //执行getExtensionClasses()方法,遍历spi文件目录,填充 loadFile方法中的各个存储变量;然后获取自适应扩展点(注:每个扩展点类型对应的扩展点加载器只有一个自适应扩展点),当不存在自适应扩展点时通过createAdaptiveExtensionClass()方法创建扩展点

private Class<?> createAdaptiveExtensionClass() //根据规则创建自适应扩展点实现,默认使用Javassit动态编译、生成自适应扩展类的字节码

private T createExtension(String name) //判断EXTENSION_INSTANCES中是否含有该键值对应的实现,不存在则创建实例,存储在EXTENSION_INSTANCES 通过injectExtension方法做依赖注入。接下来就是装饰模式的封装:如果cachedWrapperClasses中存在XXXWrapper,则通过以扩展点接口为参数的构造函数来实例化该扩展点的包装类。如接口Protocol所对应的包装类ProtocolListenerWrapper和ProtocolFilterWrapper,即每个Protocol的扩展点实现都需要经过ProtocolListenerWrapper和ProtocolFilterWrapper的包装后返回包装类。

private T injectExtension(T instance)//该方法最主要的作用是给扩展点实现类的属性(公有方法,标准的set方法写法,且入参只有一个)做依赖注入(IOC) , 通过objectFactory.getExtension获得属性的bean(直接获得object对象的是通过SpringExtensionFactory)或是属性所对应扩展点的Adaptive类(通过SpiExtensionFactor获得),第二种方式注入的对象只有在真正调用的时候才会根据url传入的key得到真正做处理的扩展点实现类。

public List<T> getActivateExtension(URL url, String key) //获取可以自动激活的扩展点,通过@Activate中的 group、value过滤等值过滤,拿到自动激活扩展点 ;如:通过使用ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); 获取对应的扩展点com.alibaba.dubbo.rpc.Fitler的自动激活扩展点实现。

public T getExtension(String name) //通过关键字查找 关键字对应的扩展点;当cachedInstances中不存在该关键字对应的扩展点实现时,使用createExtension()方法创建扩展点实现

private Class<?> getExtensionClass(String name) private Map<String, Class<?>> getExtensionClasses()//上述两个方法实现的功能是从cachedNames中读取获取name对应的扩展点实现;不存在则通过loadFile方法扫描spi配置文件,加载到到属性中。

private T createAdaptiveExtension()//当cachedAdaptiveClass属性为空时,需使用createAdaptiveExtensionClass方法动态创建自适应扩展点实现,使用javassist完成这个实现的字节码生成。

private Map<String, Class<?>> loadExtensionClasses()//使用loadFile方法加载扩展点信息至全局缓存或ExtensionLoader属性中

private void loadFile(Map<String, Class<?>> extensionClasses, String dir) //加载spi的文件,解析文件内容,逐条遍历文件中的各关键字与关键字所对应的扩展点全路径,根据规则放到不同的属性中 1.使用Adaptive注解的扩展点实现类 赋值给cachedAdaptiveClass 2.扩展点存在以扩展点接口为参数的构造方法时,将该扩展点实现放入cachedWrapperClasses中存储 即将扩展点的wrap类放入到cachedWrapperClasses中 3.不符合2中所列情况时,扩展点实现带有@Activate注解时,存入cachedActivates中 ,然后扩扩展点实现存放到cachedNames中。 最后返回cachedNames

猜你喜欢

转载自my.oschina.net/u/3426999/blog/1618314