Dubbo版本:2.6.2
dubbo是一款和spring结合比较好的框架,按照spring自定义标签规范,使用spring.handlers中定义的NamespaceHandler 来加载dubbo配置文件。
http\://dubbo.apache.org/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
DubboNamespaceHandler中注册了各种对dubbo标签的解析器
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
//dubbo中大量引用,用于排除jar冲突时的重复引入
Version.checkDuplicate(DubboNamespaceHandler.class);
}
@Override
public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.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));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
}
}
由此可见,对于几乎所有的标签,都由DubboBeanDefinitionParser进行处理,这个类主要作用就是解析xml中的相应标签属性,并最终实例化成BeanDefinition交由spring进行管理
public class DubboBeanDefinitionParser implements BeanDefinitionParser {
private static final Pattern GROUP_AND_VERION = Pattern.compile("^[\\-.0-9_a-zA-Z]+(\\:[\\-.0-9_a-zA-Z]+)?$");
private final Class<?> beanClass;
private final boolean required;
public DubboBeanDefinitionParser(Class<?> beanClass, boolean required) {
this.beanClass = beanClass;
this.required = required;
}
@SuppressWarnings("unchecked")
private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
// 实例化最终需要给Spring装载的BeanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition();
// 对应的类型由构造方法传入
beanDefinition.setBeanClass(beanClass);
// 关闭bean的延迟初始化,使之在容器启动的时候就初始化
beanDefinition.setLazyInit(false);
String id = element.getAttribute("id");
// 从目前看来,只有reference的标签时,required参数才为false
if ((id == null || id.length() == 0) && required) {
// 当id为null,需要使用name对id进行补足
String generatedBeanName = element.getAttribute("name");
if (generatedBeanName == null || generatedBeanName.length() == 0) {
if (ProtocolConfig.class.equals(beanClass)) {
generatedBeanName = "dubbo";
} else {
generatedBeanName = element.getAttribute("interface");
}
}
if (generatedBeanName == null || generatedBeanName.length() == 0) {
generatedBeanName = beanClass.getName();
}
id = generatedBeanName;
int counter = 2;
//有时会有重复的标签,比如定义多个protocol,这时就需要在id后面添加编号
while (parserContext.getRegistry().containsBeanDefinition(id)) {
id = generatedBeanName + (counter++);
}
}
if (id != null && id.length() > 0) {
if (parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
}
//向spring注册BeanDefinition并设置id属性
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
beanDefinition.getPropertyValues().addPropertyValue("id", id);
}
if (ProtocolConfig.class.equals(beanClass)) {
//将property中定义的protocol替换成该ProtocolConfig的引用
for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {
BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name);
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));