dubbo原始碼學習之dubbo的ioc和aop
阿新 • • 發佈:2019-02-05
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);
}
}