半日闲

因过竹院逢僧话,又得浮生半日闲

0%

Dubbo源码解读2-扩展点类ExtensionLoader getAdaptiveExtension方法

模块描述

该方法主要创建SPI的适配类实例

逻辑解析

  1. 先从缓存中查找,如果存在,直接返回,如果不存在,先创建,并加入缓存,再返回。
  2. 创建过程,先加载适配扩展点类,并实例化,在方法被@Inject修饰时, 对方法在进行扩展点注入。
  3. 在创建AdaptiveInstance时,先判断SPI接口的实现类是否被@Adaptive类修饰,如果被修饰,则代表该类是静态适配类,实例化并返回。
    如果不是,则需要采用字节码技术编译一个可用的类,名称为public class XXX$Adaptive{}。在构建过程中,需要判断方法是否被@Adaptive注解修饰,如果没有,则在方法体里面抛出异常。如果修饰了,则需要判断方法参数是否包含URL参数,或者方法参数类里面是否包含public getURL方法,如果没有包含,则抛出异常。包含了则生成对应的$Adaptive类,并实例化成对象返回。
  4. 在进行扩展点注入过程中,如果发现方法被@Inject修饰,则查找参数是否包含SPI接口,并需要从全局扩展点中实例化一个对象,并在执行的时候自动注入。

    相关代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    public T getAdaptiveExtension() {
    Object instance = cachedAdaptiveInstance.get();
    if (instance == null) {
    if (createAdaptiveInstanceError != null) {
    throw
    }
    synchronized (cachedAdaptiveInstance) {
    instance = cachedAdaptiveInstance.get();
    if (instance == null) {
    try {
    instance = createAdaptiveExtension();
    cachedAdaptiveInstance.set(instance);
    } catch (Throwable t) {
    createAdaptiveInstanceError = t;
    Throw
    }
    }
    }
    }
    return (T) instance;
    }
    private T createAdaptiveExtension() {
    try {
    return injectExtension((T) getAdaptiveExtensionClass().newInstance());
    } catch (Exception e) {
    throw;
    }
    }
    private T injectExtension(T instance) {
    if (objectFactory == null) {
    return instance;
    }
    try {
    for (Method method : instance.getClass().getMethods()) {
    if (!isSetter(method)) {
    continue;
    }
    if (method.getAnnotation(DisableInject.class) != null) {
    continue;
    }
    Class<?> pt = method.getParameterTypes()[0];
    if (ReflectUtils.isPrimitives(pt)) {
    continue;
    }
    String property = getSetterProperty(method);
    Inject inject = method.getAnnotation(Inject.class);
    if (inject == null) {
    injectValue(instance, method, pt, property);
    } else {
    if (!inject.enable()) {
    continue;
    }
    if (inject.type() == Inject.InjectType.ByType) {
    injectValue(instance, method, pt, null);
    } else {
    injectValue(instance, method, pt, property);
    }
    }
    }
    } catch (Exception e) {
    logger.error(e.getMessage(), e);
    }
    return instance;
    }
    private Class<?> getAdaptiveExtensionClass() {
    getExtensionClasses();
    if (cachedAdaptiveClass != null) {
    return cachedAdaptiveClass;
    }
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }
    private Map<String, Class<?>> getExtensionClasses() {
    Map<String, Class<?>> classes = cachedClasses.get();
    if (classes == null) {
    synchronized (cachedClasses) {
    classes = cachedClasses.get();
    if (classes == null) {
    classes = loadExtensionClasses();
    cachedClasses.set(classes);
    }
    }
    }
    return classes;
    }
    private Map<String, Class<?>> loadExtensionClasses() {
    cacheDefaultExtensionName();
    Map<String, Class<?>> extensionClasses = new HashMap<>();
    for (LoadingStrategy strategy : strategies) {
    loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(),
    strategy.overridden(), strategy.excludedPackages());
    loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"),
    strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
    }
    // 类加载部分
    return extensionClasses;
    }