1. 程式人生 > >dubbo原始碼學習之dubbo的ioc和aop

dubbo原始碼學習之dubbo的ioc和aop

  dubbo實現了自己的ioc注入,主要方法是ExtensionLoader裡的injectExtension(T instance)方法。

private T injectExtension(T instance) {
        try {
		    //objectFactory是dubbo的ioc容器 型別是ExtensionFactory 為dubbo的ioc提供所有的物件
            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) : "";
                           //set副檔名(Object object) 格式的方法 會根據型別和副檔名從 objectFactory中取得物件                         
						   Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
							    //呼叫instance物件的moethod方法 並將object作為引數傳入
                                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;
    }

public <T> T getExtension(Class<T> type, String name) {
	    //從SpiExtensionFactory或者SpringExtensionFactory讀取物件
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }


SpiExtensionFactory的獲取
public <T> T getExtension(Class<T> type, String name) {
	    //判斷介面是否被@spi註解 adaptive物件會根據dubbo的URL物件裡面的值來選擇介面的實現類物件
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
	   //如果型別支援的實現類大於0就返回extensionLoader的adaptive物件
            if (loader.getSupportedExtensions().size() > 0) {
                return loader.getAdaptiveExtension();
            }
        }
        return null;
    }
SpringExtensionFactory的獲取

   public <T> T getExtension(Class<T> type, String name) {
	    //從spring的context容器中根據型別和beanName查詢物件
        for (ApplicationContext context : contexts) {
            if (context.containsBean(name)) {
                Object bean = context.getBean(name);
                if (type.isInstance(bean)) {
                    return (T) bean;
                }
            }
        }
        return null;
    }

總的來說dubbo的ioc就是從dubbo的spi容器或者spring的容器中獲取bean。

  private T createExtension(String name) {
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null) {
            throw findException(name);
        }
        try {
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            injectExtension(instance);
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (wrapperClasses != null && wrapperClasses.size() > 0) {
                for (Class<?> wrapperClass : wrapperClasses) {
		//這個地方是dubbo的aop簡單實現 利用裝飾模式對原有的類進行裝飾 主要是ProtocolListenerWrapper(監聽) ProtocolFilterWrapper(過濾)
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
                    type + ")  could not be instantiated: " + t.getMessage(), t);
        }
    }