Spring如何解析Dubbo標簽


  1. 要了解Dubbo是如何解析標簽的,首先要清楚一點就是Spring如何處理自定義標簽的,因為Dubbo的標簽可以算是Spring自定義標簽的一種情況;

  2. Spring通過兩個接口來解析自定義的標簽:NamespaceHandlerBeanDefinitionParser接口;NamespaceHandler負責namespace的處理,而BeanDefinitionParser負責Bean的解析;

  3. 我們自定義標簽的時候,可以實現NamespaceHandler接口,但更多的是繼承NamespaceHandler的抽象類:NamespaceHandlerSupport,然后在classpath的META-INF目錄下編寫一個spring.handlers文件,在該文件中定義namespace的URL和namespace處理類的映射。
比如Dubbo的spring.handlers文件內容(/是轉義):

http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

  4. spring框架初始化時會加載所有classpath的spring.handlers文件,把namespace的URL和namespace處理類映射到Map中,Spring在解析的時候,遇到一些自定義的標簽的時候,會在這個Map中查找namespace處理類,使用這個使用這個自定義的處理類來進行標簽的解析工作;

  5. 同樣,Dubbo框架的namespace的處理類是DubboNamespaceHandler,也是實現了NamespaceHandlerSupport接口來處理命名空間,然后在這個類的初始化的時候給所有標簽都注冊了各自的解析器;而Dubbo的解析類DubboBeanDefinitionParser同樣也是實現了BeanDefinitionParser接口;

DubboNamespaceHandler 源代碼如此下:
/**
 * DubboNamespaceHandler
 * 
 * @author william.liangf
 * @export
 */
public class DubboNamespaceHandler extends NamespaceHandlerSupport {

    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }

    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 DubboBeanDefinitionParser(AnnotationBean.class, true));
    }

}

可以看到,Dubbo有10個標簽,每個標簽會解析到對應的實體上,每個實體中的屬性對應標簽中的屬性,比如ApplicationConfig類:

/**
 * ApplicationConfig
 * 
 * @author william.liangf
 * @export
 */
public class ApplicationConfig extends AbstractConfig {

    private static final long    serialVersionUID = 5508512956753757169L;

    // 應用名稱
    private String               name;

    // 模塊版本
    private String               version;

    // 應用負責人
    private String               owner;

    // 組織名(BU或部門)
    private String               organization;

    // 分層
    private String               architecture;

    // 環境,如:dev/test/run
    private String               environment;

    // Java代碼編譯器
    private String               compiler;

    // 日志輸出方式
    private String               logger;

    // 注冊中心
    private List<RegistryConfig> registries;

    // 服務監控
    private MonitorConfig        monitor;

    // 是否為缺省
    private Boolean              isDefault;

    public ApplicationConfig() {
    }
    
    public ApplicationConfig(String name) {
        setName(name);
    }
    
    @Parameter(key = Constants.APPLICATION_KEY, required = true)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        checkName("name", name);
        this.name = name;
        if (id == null || id.length() == 0) {
            id = name;
        }
    }

    @Parameter(key = "application.version")
    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        checkMultiName("owner", owner);
        this.owner = owner;
    }

    public String getOrganization() {
        return organization;
    }

    public void setOrganization(String organization) {
        checkName("organization", organization);
        this.organization = organization;
    }

    public String getArchitecture() {
        return architecture;
    }

    public void setArchitecture(String architecture) {
        checkName("architecture", architecture);
        this.architecture = architecture;
    }

    public String getEnvironment() {
        return environment;
    }

    public void setEnvironment(String environment) {
        checkName("environment", environment);
        if(environment != null) {
            if (! ("develop".equals(environment) || "test".equals(environment) || "product".equals(environment))) {
                throw new IllegalStateException("Unsupported environment: " + environment + ", only support develop/test/product, default is product.");
            }
        }
        this.environment = environment;
    }

    public RegistryConfig getRegistry() {
        return registries == null || registries.size() == 0 ? null : registries.get(0);
    }

    public void setRegistry(RegistryConfig registry) {
        List<RegistryConfig> registries = new ArrayList<RegistryConfig>(1);
        registries.add(registry);
        this.registries = registries;
    }

    public List<RegistryConfig> getRegistries() {
        return registries;
    }

    @SuppressWarnings({ "unchecked" })
    public void setRegistries(List<? extends RegistryConfig> registries) {
        this.registries = (List<RegistryConfig>)registries;
    }

    public MonitorConfig getMonitor() {
        return monitor;
    }

    public void setMonitor(MonitorConfig monitor) {
        this.monitor = monitor;
    }

    public void setMonitor(String monitor) {
        this.monitor = new MonitorConfig(monitor);
    }

    public String getCompiler() {
        return compiler;
    }

    public void setCompiler(String compiler) {
        this.compiler = compiler;
        AdaptiveCompiler.setDefaultCompiler(compiler);
    }

    public String getLogger() {
        return logger;
    }

    public void setLogger(String logger) {
        this.logger = logger;
        LoggerFactory.setLoggerAdapter(logger);
    }

    public Boolean isDefault() {
        return isDefault;
    }

    public void setDefault(Boolean isDefault) {
        this.isDefault = isDefault;
    }

}

Dubbo版本:2.8.4.5


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM