五Dubbo服务引用源码分析--1消费端启动

五Dubbo服务引用源码分析--1消费端启动

在消费端consumer引用服务进行分析时,首先看Dubbo的开发者手册,把握分析的切入点,并全局把握大致的流程。

image-20230313113206021

1 服务消费的过程中,首先是引用配置的初始化--即ReferenceConfig初始化,需要加载consumer.xml配置信息,将referenceBean的beandefinition加载入spring的IOC容器的beanDefinitionMap中;

2 然后,完成实例化并初始化referenceBean的过程中,执行referenceConfig.init()方法,调用protocol.refer方法生成Invoker实例(此处是consumer端的关键);

3 随后把invoker转换为客户端需要的接口;

4 服务调用的过程中,调用referenceBean.getObject获取代理对象,然后执行服务的引用操作。

服务引用部分,仍旧以DubboDemo为例,进行源码追踪与分析。

image-20221221154055475

consumer端启动代码如下:

image-20221221154229290

5.0 消费端启动(初始化)

对于ReferenceBean,其继承结构如下

image-20230313113223435
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {

    public Object getObject() throws Exception {
        return get();
    }
  /**referenceConfig方法
      public synchronized T get() {
        if (destroyed) {
            throw new IllegalStateException("Already destroyed!");
        }
        if (ref == null) {
            init();
        }
        return ref;  ref是referenceBean所代理的目标类,所创建的代理类对象
    }*/
    //初始化方法
    public void afterPropertiesSet() throws Exception {

1 可知其实现了bean的周期方法的接口,在初始化时调用;

2 此外,实现FactoryBean,getBean获取对象时,通过getObject获取真正的bean;

3 然后继承ReferenceConfig,实现了dubbo的消费端信息的配置。

5.0.1 解析referenceBean的xml

在启动consumer端后,解析consumer.xml中配置的dubbo:reference的配置信息

image-20221221180221525 image-20221221180346090

解析后,在spring的IOC容器中的beanDefinitionMap中加入如下的beandefinition定义:

image-20221221110058148

image-20221221111144844

将ReferenceBean以permissionService的id存入IOC容器的map中。

5.0.2 初始化referenceBean

在初始化bean时,会根据自定义的Initmethod方法,完成对ReferenceBean的初始化工作。

TAG1 referenceBean自定义初始化
referenceBean
  
@SuppressWarnings({ "unchecked"})
    public void afterPropertiesSet() throws Exception {
  			//初始化过程中,此处为null
        if (getConsumer() == null) {
            Map<String, ConsumerConfig> consumerConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class, false, false);
            if (consumerConfigMap != null && consumerConfigMap.size() > 0) {
                ConsumerConfig consumerConfig = null;
                for (ConsumerConfig config : consumerConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (consumerConfig != null) {
                            throw new IllegalStateException("Duplicate consumer configs: " + consumerConfig + " and " + config);
                        }
                        consumerConfig = config;
                    }
                }
                if (consumerConfig != null) {
                    setConsumer(consumerConfig);
                }
            }
        }
        if (getApplication() == null
                && (getConsumer() == null || getConsumer().getApplication() == null)) {
          //referenceBean实现applicationContextAware,会自动注入,此处applicationContext不为null
          //然后这里从spring的applicationContext种获取在xml内配置的dubbo的ApplicationConfig
            Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
            if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
                ApplicationConfig applicationConfig = null;
                for (ApplicationConfig config : applicationConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (applicationConfig != null) {
                            throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
                        }
                        applicationConfig = config;
                    }
                }
                if (applicationConfig != null) {
                  //设置referenceBean的dubbo-applicationConfig
                    setApplication(applicationConfig);
                }
            }
        }
        if (getModule() == null
                && (getConsumer() == null || getConsumer().getModule() == null)) {
            Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
            if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
                ModuleConfig moduleConfig = null;
                for (ModuleConfig config : moduleConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (moduleConfig != null) {
                            throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
                        }
                        moduleConfig = config;
                    }
                }
                if (moduleConfig != null) {
                    setModule(moduleConfig);
                }
            }
        }
        if ((getRegistries() == null || getRegistries().size() == 0)
                && (getConsumer() == null || getConsumer().getRegistries() == null || getConsumer().getRegistries().size() == 0)
                && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
          //然后这里从spring的applicationContext种获取在xml内配置的dubbo的RegistryConfig
            Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
            if (registryConfigMap != null && registryConfigMap.size() > 0) {
                List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
                for (RegistryConfig config : registryConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        registryConfigs.add(config);
                    }
                }
                if (registryConfigs != null && registryConfigs.size() > 0) {
                  //设置referenceBean的注册中心配置
                    super.setRegistries(registryConfigs);
                }
            }
        }
        if (getMonitor() == null
                && (getConsumer() == null || getConsumer().getMonitor() == null)
                && (getApplication() == null || getApplication().getMonitor() == null)) {
            Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
            if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
                MonitorConfig monitorConfig = null;
                for (MonitorConfig config : monitorConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (monitorConfig != null) {
                            throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
                        }
                        monitorConfig = config;
                    }
                }
                if (monitorConfig != null) {
                    setMonitor(monitorConfig);
                }
            }
        }
  			//是否在加载时,立刻getObject()初始化ReferenceBean---默认懒加载
        Boolean b = isInit();
        if (b == null && getConsumer() != null) {
            b = getConsumer().isInit();
        }
        if (b != null && b.booleanValue()) {
            getObject();
        }
    }

在ReferenceBean的afterPropertiesSet方法中,初始化referenceConfig的applicationConfig、registryConfig等属性。

image-20221221193702430

ReferenceBean的过程,总结如下:

image-20221222090049970

其中,interfaceClass属性,用来匹配IOC容器内factoryBean.getObject()所代理创建的对象的类型。用来在applicationContext.getBean(DemoService.class)匹配IOC中的beanname。

TAG2 ReferenceBean.getBean(DemoService.class)执行时机
TAG2.0 Dubbo2.6.4及以下版本问题(2.6.9)

在spring容器实例化(不是初始化过程)时,总是发现ReferenceBean在存入spring一级缓存后,它的ref(就是DemoService服务类的动态代理类被默认初始化创建了,但是没有执行ReferenceBean.getObject()初始化ref这一步。

image-20221223175928647

image-20221223173018831

个人调试源码过程中,使用的Dubbo2.5.3,发现在跟踪源码调试ReferenceBean,了解ref的代理创建过程时候,总是遇到这个问题,也调试和纠结了许久,后来发现是2.6.4及以下版本的问题,并且在pull request #2754 中已经修复该问题,并在Dubbo2.6.5版本中修改。如果使用低版本dubbo,可以按如下修改IDEA默认的配置:

image-20221223180519976

这里,是在debug模式下,取消"toString"的override。因为,在debug模式下,IDEA会通过toString()方法,获取对象对应的信息。而在ReferenceBean执行过程中,显示信息执行的toString(),调用的是父类AbstractConfig.toString()方法:

   public String toString() {
        try {
            StringBuilder buf = new StringBuilder();
            buf.append("<dubbo:");
            buf.append(getTagName(getClass()));
          	//获取当前config类内方法对象
            Method[] methods = getClass().getMethods();
            for (Method method : methods) {
                try {
                    String name = method.getName();
                  //这里没有过滤掉getObject()方法
                    if ((name.startsWith("get") || name.startsWith("is"))
                            && !"getClass".equals(name) && !"get".equals(name) && !"is".equals(name)
                            && Modifier.isPublic(method.getModifiers())
                            && method.getParameterTypes().length == 0
                            && isPrimitive(method.getReturnType())) {
                        int i = name.startsWith("get") ? 3 : 2;
                        String key = name.substring(i, i + 1).toLowerCase() + name.substring(i + 1);
                      //getObject方法被反射调用,从而实现referenceBean中ref的初始化操作
                        Object value = method.invoke(this);
                        if (value != null) {
                            buf.append(" ");
                            buf.append(key);
                            buf.append("=\"");
                            buf.append(value);
                            buf.append("\"");
                        }
                    }
                } catch (Exception e) {
                    logger.warn(e.getMessage(), e);
                }
            }
            buf.append(" />");
            return buf.toString();
        } catch (Throwable t) {
            logger.warn(t.getMessage(), t);
            return super.toString();
        }
    }

从上述的过程知道出问题以及在debug模式下修改的原因。

TAG2.1 ReferenceBean初始化

referenceBean作为FactoryBean类,其在执行实例化、初始化后,会最终向一级缓存中添加如下的k:v对:

key(permissionService):value(ReferenceBean)。此时,已经执行完TAG1的自定义初始化过程。

image-20230313113317171

此时,一级缓存中存储name为"permissionService"、具体实例为ReferenceBean。此时,referenceBean内代理对象ref,尚未经过getObject()进行创建代理对象。

TAG2.2 context.getObject调用时机(spring相关内容)

对于服务引用获取的DemoService,不是要referenceBean实例,而是获取远程调用的代理对象,并通过该proxy对象调用远程dubbo服务。

image-20221222094014435

在5.0中,向IOC容器的beandefinitionMap中传入permissionService=beanDefinition(referencenBean),然后跟入context.getBean(DemoService.class)

AbstractApplicationContext	
  //根据DemoService.class类型,获取bean
public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}

DefaultListableBeanFactory
		@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		return getBean(requiredType, (Object[]) null);
	}
	
DefaultListableBeanFactory
		public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
		Assert.notNull(requiredType, "Required type must not be null");
  //获取type类型在spring的IOC容器中的对象
		Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
		if (resolved == null) {
			throw new NoSuchBeanDefinitionException(requiredType);
		}
		return (T) resolved;
	}
	
		private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
//TAG0 resolveNamedBean 根据类型type,获取springIOC中的bean
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}
		BeanFactory parent = getParentBeanFactory();
		if (parent instanceof DefaultListableBeanFactory) {
			return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
		}
		else if (parent != null) {
			ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
			if (args != null) {
				return parentProvider.getObject(args);
			}
			else {
				return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
			}
		}
		return null;
	}

//TAG0 resolveNamedBean
	private <T> NamedBeanHolder<T> resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

		Assert.notNull(requiredType, "Required type must not be null");
//TAG1 getBeanNamesForType
    //对于getBean(type),对于参数type类型,获取IOC容器中对应的beanName
    //逻辑:从beanFactory的beannames中遍历,并获取beandefinition,如果当前bean是factoryBean,获取其参数interfaceClass,表示当前factoryBean的getBean获取的具体对象类型
		String[] candidateNames = getBeanNamesForType(requiredType);

		if (candidateNames.length > 1) {
			List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}

    //根据type只匹配到一个候选者时
		if (candidateNames.length == 1) {
//TAG2 resolveNamedBean
      //"permissionService",DemoService---获取对应的bean
			return resolveNamedBean(candidateNames[0], requiredType, args);
		}
		else if (candidateNames.length > 1) {
			Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
			for (String beanName : candidateNames) {
				if (containsSingleton(beanName) && args == null) {
					Object beanInstance = getBean(beanName);
					candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
				}
				else {
					candidates.put(beanName, getType(beanName));
				}
			}
			String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
			if (candidateName == null) {
				candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
			}
			if (candidateName != null) {
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance == null) {
					return null;
				}
				if (beanInstance instanceof Class) {
					return resolveNamedBean(candidateName, requiredType, args);
				}
				return new NamedBeanHolder<>(candidateName, (T) beanInstance);
			}
			if (!nonUniqueAsNull) {
				throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
			}
		}

		return null;
	}

//TAG2 resolveNamedBean
	@Nullable
	private <T> NamedBeanHolder<T> resolveNamedBean(
			String beanName, ResolvableType requiredType, @Nullable Object[] args) throws BeansException {
		//然后根据匹配到的beanname,获取bean对象
		Object bean = getBean(beanName, null, args);
		if (bean instanceof NullBean) {
			return null;
		}
		return new NamedBeanHolder<T>(beanName, adaptBeanInstance(beanName, bean, requiredType.toClass()));
	}

getBeanNamesForType方法中,根据getBean(type)传入的类型,从springIOC注册的beandefinitionNames中遍历,并获取beandefinition,如果当前bean是factoryBean,获取其参数interfaceClass,表示当前factoryBean的getBean获取的具体对象类型。其匹配逻辑如下:

image-20221223095143061

image-20221223095431634

AbstractBeanFactory
	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object beanInstance;

  	//从缓存中获取
		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
//TAG1 
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		
		else{……………………略}
AbstractBeanFactory
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
	/** ………………………………………………略*/

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
      //this.factoryBeanObjectCache中获取(尚未缓存)
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
      //从factoryBean的getObject获取对象
//TAG1 
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}


FactoryBeanRegistrySupport
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
        //从factoryBean中getObject对象,缓存
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
//TAG2 
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
              //存入缓存
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
  
  	private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
//这里从ReferenceBean.getObject()获取demoService对象
				object = factory.getObject();
			}
		}

从factoryBean.getObject()获取对象后,会以demoservice:proxy$0为k:v键值对,存入spring的FactoryBeanObjectCache缓存中。

image-20221227113503115

posted @ 2023-03-13 14:45  LeasonXue  阅读(169)  评论(0)    收藏  举报