private final Class<?> beanClass; // Bean对应的Class类(即Config的Class类)
private final boolean required; // 是否必须(即Config类的id是否必须)
private static RootBeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) { //ParserContext:通过bean定义解析过程传递的上下文,封装所有相关配置和状态,嵌套在XmlReaderContext内
RootBeanDefinition beanDefinition = new RootBeanDefinition(); //创建spring的Bean实例
beanDefinition.setBeanClass(beanClass); //设置Bean对应的class类,如MethodConfig.class
beanDefinition.setLazyInit(false); //设置是否延迟初始化,false:在spring容器启动时,就会创建Bean实例
String id = resolveAttribute(element, "id", parserContext); //解析属性id的值
/**
* 处理属性id的值,若属性id为空且是必须的,则尝试获取name、interface属性对应的值,若还为空则获取bean的名称
*/
if (StringUtils.isEmpty(id) && required) { //未设置属性id时,使用其它属性产生id值
String generatedBeanName = resolveAttribute(element, "name", parserContext); //解析属性name的值
if (StringUtils.isEmpty(generatedBeanName)) {
if (ProtocolConfig.class.equals(beanClass)) {
generatedBeanName = "dubbo";
} else {
generatedBeanName = resolveAttribute(element, "interface", parserContext);
}
}
if (StringUtils.isEmpty(generatedBeanName)) {
generatedBeanName = beanClass.getName(); //bean的名称如:class org.apache.dubbo.config.ApplicationConfig
}
id = generatedBeanName;
int counter = 2;
while (parserContext.getRegistry().containsBeanDefinition(id)) { //若bean已存在,则加上计数标识,直到没有重复的id为止
id = generatedBeanName + (counter++); // count++的值从2开始递增,变量count在前,count++就是加之前的值
}
}
if (StringUtils.isNotEmpty(id)) {
if (parserContext.getRegistry().containsBeanDefinition(id)) { //判断已经注册的Bean中是否有重复的id
throw new IllegalStateException("Duplicate spring bean id " + id);
}
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition); // 向spring注册中心注册bean实例(将id作为Bean的名称)
beanDefinition.getPropertyValues().addPropertyValue("id", id); // 设置bean的id属性
}
/**
* 对指定的bean进行处理,如ProtocolConfig、ServiceBean、ProviderConfig、ConsumerConfig等
*/
if (ProtocolConfig.class.equals(beanClass)) {
for (String name : parserContext.getRegistry().getBeanDefinitionNames()) { //遍历已注册的bean对应的名称列表
BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name); //获取指定bean名称对应的BeanDefinition实例
PropertyValue property = definition.getPropertyValues().getPropertyValue("protocol");
if (property != null) {
Object value = property.getValue();
if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {
definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));
}
}
}
} else if (ServiceBean.class.equals(beanClass)) {
String className = resolveAttribute(element, "class", parserContext);
if (StringUtils.isNotEmpty(className)) { //在 中设置class属性时进入
RootBeanDefinition classDefinition = new RootBeanDefinition(); //根bean定义也可以用于注册单个bean定义
classDefinition.setBeanClass(ReflectUtils.forName(className));
classDefinition.setLazyInit(false);
parseProperties(element.getChildNodes(), classDefinition, parserContext);
beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl")); //BeanDefinitionHolder:带有名称和别名的bean定义的Holder
// 此处的bean实例,会在bean的名称后面加上Impl,如:org.apache.dubbo.demo.DemoService + "Impl",对应的实现类是org.apache.dubbo.demo.DemoServiceImpl
}
} else if (ProviderConfig.class.equals(beanClass)) { //对 中的嵌套 元素进行解析
parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
} else if (ConsumerConfig.class.equals(beanClass)) { //对 中的嵌套 元素进行解析
parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);
}
Set<String> props = new HashSet<>();
ManagedMap parameters = null; //托管的Map(Spring的标签集合类,用于保存被托管的Map)
for (Method setter : beanClass.getMethods()) { //遍历Config中的set方法提取出属性名,然后通过XML的Element解析出对应的属性值,最后依次设置到Config类关联的Bean的属性中
String name = setter.getName();
if (name.length() > 3 && name.startsWith("set")
&& Modifier.isPublic(setter.getModifiers())
&& setter.getParameterTypes().length == 1) {
Class<?> type = setter.getParameterTypes()[0];
String beanProperty = name.substring(3, 4).toLowerCase() + name.substring(4); //解析出属性名,如方法名为setName,属性名为name
String property = StringUtils.camelToSplitName(beanProperty, "-"); //按分隔符方式处理属性名称
props.add(property); //将属性加到属性集合中
// check the setter/getter whether match (检查set、get方法是否匹配)
Method getter = null;
try {
getter = beanClass.getMethod("get" + name.substring(3), new Class<?>[0]);//获取指定的属性对应的get方法,如getName
} catch (NoSuchMethodException e) {
try {
getter = beanClass.getMethod("is" + name.substring(3), new Class<?>[0]); //处理is开头的方法,比如ApplicationConfig中的isDefault()方法
} catch (NoSuchMethodException e2) { //允许没有get方法,比如EnvironmentAware,只有set方法,不能抛出异常,不然引起应用启动失败
// ignore, there is no need any log here since some class implement the interface: EnvironmentAware,
// ApplicationAware, etc. They only have setter method, otherwise will cause the error log during application start up.
}
}
if (getter == null
|| !Modifier.isPublic(getter.getModifiers())
|| !type.equals(getter.getReturnType())) { //若没有找到符合条件的get方法,则本次不处理,跳到下次循环
continue;
}
/**
* 从XML元素中读取Config类属性对应的值,并设置到Bean的属性中
*/
if ("parameters".equals(property)) {
parameters = parseParameters(element.getChildNodes(), beanDefinition, parserContext); //解析 元素的值
} else if ("methods".equals(property)) {
parseMethods(id, element.getChildNodes(), beanDefinition, parserContext); //解析 元素的值
} else if ("arguments".equals(property)) {
parseArguments(id, element.getChildNodes(), beanDefinition, parserContext); //解析 元素的值
} else { //对常规属性做处理
String value = resolveAttribute(element, property, parserContext); //解析XML中元素对应的属性值
if (value != null) { //若属性值为不为空,则对应处理(即XML中设置了对应的属性值)
value = value.trim(); //过滤字符串的前后空格(即过滤掉空字符串)
if (value.length() > 0) {
if ("registry".equals(property) && RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value)) {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress(RegistryConfig.NO_AVAILABLE);
beanDefinition.getPropertyValues().addPropertyValue(beanProperty, registryConfig);
} else if ("provider".equals(property) || "registry".equals(property) || ("protocol".equals(property) && AbstractServiceConfig.class.isAssignableFrom(beanClass))) {
// Class中方法isAssignableFrom():判断当前class是否与参数中指定的class相同,或者是参数指定的class的父类或父接口(主语是当前class,如上的主语即为:AbstractServiceConfig)
beanDefinition.getPropertyValues().addPropertyValue(beanProperty + "Ids", value);
} else {
Object reference;
if (isPrimitive(type)) { //对基本类型的属性处理(基本类型进行了扩展,包含String、Date等)
if ("async".equals(property) && "false".equals(value)
|| "timeout".equals(property) && "0".equals(value) //每个判断条件作为一行,清晰明了
|| "delay".equals(property) && "0".equals(value)
|| "version".equals(property) && "0.0.0".equals(value)
|| "stat".equals(property) && "-1".equals(value)
|| "reliable".equals(property) && "false".equals(value)) {
// backward compatibility for the default value in old version's xsd(向后兼容旧版本的XSD中的默认值)
value = null; //若旧版本的属性满足条件,则将属性值设置为null
}
reference = value;
// 对方法元素中的onreturn、onthrow、oninvoke属性进行处理
} else if (ONRETURN.equals(property) || ONTHROW.equals(property) || ONINVOKE.equals(property)) {
int index = value.lastIndexOf("."); //待覆盖调试:事件通知允许Consumer端在调用之前、调用之后或出现异常时,触发oninvoke、onreturn、onthrow三个事件。 https://dubbo.apache.org/zh/docs/advanced/events-notify/
String ref = value.substring(0, index); //onreturn、onthrow、oninvoke的属性值,必须要以 xxx.方法名形式,若没有".",则会由于[0,-1)报字符串区间错误 "String index out of range: -1"
String method = value.substring(index + 1);
reference = new RuntimeBeanReference(ref);
beanDefinition.getPropertyValues().addPropertyValue(property + METHOD, method);
} else { //解析ref属性
if ("ref".equals(property) && parserContext.getRegistry().containsBeanDefinition(value)) {
BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value);
if (!refBean.isSingleton()) { //检查暴露的服务是不是单例
throw new IllegalStateException("The exported service ref " + value + " must be singleton! Please set the " + value + " bean scope to singleton, eg: + value + "\" scope=\"singleton\" ...>");
}
}
reference = new RuntimeBeanReference(value); //创建指定名称的bean
}
beanDefinition.getPropertyValues().addPropertyValue(beanProperty, reference); //为bean添加属性值
}
}
}
}
}
}
NamedNodeMap attributes = element.getAttributes(); //获取元素的属性节点列表
int len = attributes.getLength();
for (int i = 0; i < len; i++) {
Node node = attributes.item(i);
String name = node.getLocalName();
if (!props.contains(name)) { //处理未处理过的属性节点
if (parameters == null) {
parameters = new ManagedMap();
}
String value = node.getNodeValue();
parameters.put(name, new TypedStringValue(value, String.class));
}
}
if (parameters != null) { //设置beanDefinition的parameters属性值
beanDefinition.getPropertyValues().addPropertyValue("parameters", parameters);
}
return beanDefinition;
}
private static void parseNested(Element element, ParserContext parserContext, Class<?> beanClass, boolean required, String tag, String property, String ref, BeanDefinition beanDefinition) {
NodeList nodeList = element.getChildNodes(); //获取子节点列表
if (nodeList == null) {
return;
}
boolean first = true;
for (int i = 0; i < nodeList.getLength(); i++) { //可以有多个内嵌节点
Node node = nodeList.item(i);
if (!(node instanceof Element)) {
continue;
}
if (tag.equals(node.getNodeName()) //带上命名空间的节点名称,如dubbo:service(按指定的tag查找Node)
|| tag.equals(node.getLocalName())) { //去掉命名空间的名称,如service
if (first) { //有多个元素时,如,只有第一个元素才处理default值
first = false; //处理好第一个元素后,更改该标志
String isDefault = resolveAttribute(element, "default", parserContext); // default: 是否为缺省协议,用于多协议
if (StringUtils.isEmpty(isDefault)) { //处理默认属性default
beanDefinition.getPropertyValues().addPropertyValue("default", "false");
}
}
// 内部嵌套的元素,按单个元素解析的方式依次解析
BeanDefinition subDefinition = parse((Element) node, parserContext, beanClass, required); //获取嵌套元素对应的Bean,如中
if (subDefinition != null && StringUtils.isNotEmpty(ref)) { //依赖的bean用RuntimeBeanReference表示
subDefinition.getPropertyValues().addPropertyValue(property, new RuntimeBeanReference(ref));
}
}
}
}
private static void parseProperties(NodeList nodeList, RootBeanDefinition beanDefinition, ParserContext parserContext) {
if (nodeList == null) {
return;
}
for (int i = 0; i < nodeList.getLength(); i++) { //NodeList: 提供了有序节点的抽象节点的集合
if (!(nodeList.item(i) instanceof Element)) {
continue;
}
Element element = (Element) nodeList.item(i);
if ("property".equals(element.getNodeName()) //只对属性节点处理
|| "property".equals(element.getLocalName())) {
String name = resolveAttribute(element, "name", parserContext); //解析中的name属性
if (StringUtils.isNotEmpty(name)) {
String value = resolveAttribute(element, "value", parserContext);
String ref = resolveAttribute(element, "ref", parserContext);
if (StringUtils.isNotEmpty(value)) { //解析基本属性
beanDefinition.getPropertyValues().addPropertyValue(name, value); //属性值列表beanDefinition.getPropertyValues(), 对应的值
} else if (StringUtils.isNotEmpty(ref)) { //解析含有引用的属性,创建对应的bean
beanDefinition.getPropertyValues().addPropertyValue(name, new RuntimeBeanReference(ref));
} else {
throw new UnsupportedOperationException("Unsupported + name + "\"> sub tag, Only supported + name + "\" ref=\"...\" /> or + name + "\" value=\"...\" />");
}
}
}
}
}
private static ManagedMap parseParameters(NodeList nodeList, RootBeanDefinition beanDefinition, ParserContext parserContext) {
if (nodeList == null) { //NodeList表示一个有顺序的节点列表
return null;
}
ManagedMap parameters = null; //托管的Map,用来保存map的值
for (int i = 0; i < nodeList.getLength(); i++) { //可以有多个元素,如:
if (!(nodeList.item(i) instanceof Element)) { //若元素不是Element实例,则不处理
continue;
}
Element element = (Element) nodeList.item(i);
if ("parameter".equals(element.getNodeName())
|| "parameter".equals(element.getLocalName())) { //只处理
if (parameters == null) {
parameters = new ManagedMap();
}
String key = resolveAttribute(element, "key", parserContext); //解析 元素中的key
String value = resolveAttribute(element, "value", parserContext); //解析 元素中的value
boolean hide = "true".equals(resolveAttribute(element, "hide", parserContext));
if (hide) { //是否隐藏,若需要隐藏,加上前缀
key = HIDE_KEY_PREFIX + key;
}
parameters.put(key, new TypedStringValue(value, String.class)); //多个 时,若key重复,value值会被覆盖(TypedStringValue:存储了string值,已经要转换的目标类型,类型转换由bean工厂处理)
}
}
return parameters; //此处没有直接添加到bean的属性中,而是在DubboBeanDefinitionParser#parse方法的最后添加的
}
public void init() { //在解析自定义元素前,进行初始化操作(设置父类NamespaceHandlerSupport的Map parsers,即设置元素名与bean解析器的映射)
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("config-center", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
registerBeanDefinitionParser("metadata-report", new DubboBeanDefinitionParser(MetadataReportConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("metrics", new DubboBeanDefinitionParser(MetricsConfig.class, true));
registerBeanDefinitionParser("ssl", new DubboBeanDefinitionParser(SslConfig.class, true));
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true)); //将元素名与对应的bean进行对应
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser()); //对应注解解析器
}
DubboBeanUtils#registerCommonBeans功能用途是什么?
是怎样加载到自定义的DubboNamespaceHandler的?
XML关联信息介绍
DOM中的节点Node介绍: