1. 程式人生 > >Dubbo原始碼分析:Dubbo自己實現的IOC

Dubbo原始碼分析:Dubbo自己實現的IOC

  在建立自適應例項時,都會呼叫ExtensionLoader的injectExtension方法:

   @SuppressWarnings("unchecked")
    private T createAdaptiveExtension() {
        try {
            /**
             * 傳入自適應例項注入到ExtensionLoader
             */
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }
private T injectExtension(T instance) {
        try {
            /**
             * 必須要有物件工廠
             */
            if (objectFactory != null) {
                for (Method method : instance.getClass().getMethods()) {
                    if (method.getName().startsWith("set")
                            && method.getParameterTypes().length == 1
                            && Modifier.isPublic(method.getModifiers())) {
                        Class<?> pt = method.getParameterTypes()[0];
                        try {
                            String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                            Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
                                method.invoke(instance, object);
                            }
                        } catch (Exception e) {
                            logger.error("fail to inject via method " + method.getName()
                                    + " of interface " + type.getName() + ": " + e.getMessage(), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return instance;
    }

        dubbo中的IOC例項是通過ExtensionFactory實現的,其實就是檢測擴充套件實現類有沒有通過set方法設定的屬性,如果有,就通過ExtensionFactory載入而設定。
ExtensionFactory的類實現體系:

    在構造ExtensionLoader物件時,有個物件extensionFactory是必須要建立的,可以看到它就是用自適應例項,而ExtensionFatocry的自適應例項便是AdaptiveExtensionFactory,通過下面它的原始碼,我們可以發現,它維護了其他非自適應擴充套件例項,其實也就兩個SpiExtensionFactory和SpringExtensionFactory。嘗試用這兩個例項去載入,載入到便返回。

@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
    
    private final List<ExtensionFactory> factories;
    
    public AdaptiveExtensionFactory() {
        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
        for (String name : loader.getSupportedExtensions()) {
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

    public <T> T getExtension(Class<T> type, String name) {
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }

}

       ExtensionFatocry 可以理解為物件工廠,只不過這裡的對應就是Dubbo中的擴充套件Extension,AdaptiveExtensionFactory可以理解為通用擴充套件實現獲取的入口,至於具體的獲取方式分為兩種,如果一種是通過Dubbo 自己的SPI方式載入到的擴充套件,同時還支援複用Srping 的方式,可以看看這兩種實現的程式碼便可知:

public class SpiExtensionFactory implements ExtensionFactory {

    public <T> T getExtension(Class<T> type, String name) {
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
            if (loader.getSupportedExtensions().size() > 0) {
                return loader.getAdaptiveExtension();
            }
        }
        return null;
    }

}

public class SpringExtensionFactory implements ExtensionFactory {
    
    private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
    
    public static void addApplicationContext(ApplicationContext context) {
        contexts.add(context);
    }

    public static void removeApplicationContext(ApplicationContext context) {
        contexts.remove(context);
    }

    @SuppressWarnings("unchecked")
    public <T> T getExtension(Class<T> type, String name) {
        for (ApplicationContext context : contexts) {
            if (context.containsBean(name)) {
                Object bean = context.getBean(name);
                if (type.isInstance(bean)) {
                    return (T) bean;
                }
            }
        }
        return null;
    }

}