spring解析dubbo标签

1、spring自定义标签的步骤(参考https://my.oschina.net/lenglingx/blog/889662)

a、编写xsd文件描述自定义的元素。看下面的代码实例,这里定义了application。其中上面的代码是具体的元素定义,下面的是自定义元素名。






    
        
            
                
            
        
        
            
                
            
        
        
            
                
            
        
    




    
        
            
        
    

 

b、编写标签对应的实体类:

public class Application {
    private String id;
    private String name;
    private String version;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getVersion() {
        return version;
    }

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

    @Override
    public String toString() {
        return "Application [id=" + id + ", name=" + name + ", version=" + version + "]";
    }

}

c、编写标签的解析类

/**  
 * All rights Reserved, Designed By www.tydic.com
 * @Title:  ApplicationBeanDefinitionParser.java   
 * @Package ApplicationBeanDefinitionParser   
 * @Description:    TODO(用一句话描述该文件做什么)   
 * @author: andyzhu    
 * @date:   2018年10月8日 上午11:14:30   
 * @version V1.0 
 * @Copyright: 2018 www.acc.com Inc. All rights reserved. 
 * 注意:禁止外泄以及用于其他的商业目
 */  
package cn.andy.testdubbo;



import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

/**
 * @author sks
 *
 */
public class ApplicationBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    private final Class beanClass;

    private final boolean required;
    
    public ApplicationBeanDefinitionParser(Class beanClass, boolean required) {
        this.beanClass = beanClass;
        this.required = required;
    }

    protected Class getBeanClass(Element element) {
        return Application.class;
    }

    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        String id = element.getAttribute("id");
        String name = element.getAttribute("name");
        String version = element.getAttribute("version");
        if (StringUtils.hasText(id)) {
            bean.addPropertyValue("id", id);
        }
        if (StringUtils.hasText(name)) {
            bean.addPropertyValue("name", name);
        }
        if (StringUtils.hasText(version)) {
            bean.addPropertyValue("version", version);
        }
    }
}

d 、编写命令空间处理类,指定自定义的标签的解析类。

/**  
 * All rights Reserved, Designed By www.tydic.com
 * @Title:  TtdubboNamespaceHandler.java   
 * @Package cn.andy.testdubbo   
 * @Description:    TODO(用一句话描述该文件做什么)   
 * @author: andyzhu    
 * @date:   2018年10月8日 下午1:58:31   
 * @version V1.0 
 * @Copyright: 2018 www.acc.com Inc. All rights reserved. 
 * 注意:禁止外泄以及用于其他的商业目
 */  
package cn.andy.testdubbo;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

/**
 * @author sks
 *
 */
public class TtdubboNamespaceHandler extends NamespaceHandlerSupport {

    /* (non-Javadoc)
     * @see org.springframework.beans.factory.xml.NamespaceHandler#init()
     */
    @Override
    public void init() {
        // TODO Auto-generated method stub
        registerBeanDefinitionParser("application", new ApplicationBeanDefinitionParser(Application.class, true));
        
    }

}

e、编写spring.handlers和spring.schemas,这两个文件都在resources目录下的META-INF文件夹中

spring.handlers文件内容,http后面的\是转义字符,注意中间的等号

http\://ttdubbo.oschina.net/schema/ttdubbo=cn.andy.testdubbo.TtdubboNamespaceHandler

spring.schemas文件内容:

http\://ttdubbo.oschina.net/schema/ttdubbo.xsd=META-INF/ttdubbo.xsd

f、测试

在spring的xml文件中定义:




    
    
    
    
    
    
    
    
    
    
        
    
    
    
    
    
    
    
    


然后,在测试文件中

public class Test {
    
    public static void main(String[] args) {
        
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-service.xml");
        
        Application application1 = (Application) context.getBean("app1");
        System.out.println(application1.toString());
        
        
        
        System.out.println("Hello World!");
    }

}

例子下载地址https://download.csdn.net/download/andyzhu_2005/10814375

2、 dubbo的标签解析

通过上面的流程,来看看dubbo的标签解析是否是这样子的:

a、在dubbo的源码目录下的META-INF文件夹中,找到的dubbo.xsd文件。里面有各个标签的元素定义:我们关注两个,service和reference标签


        
            
                
                    
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                            
                        
                    
                
                
                    
                        
                            
                        
                    
                
                
                    
                        
                            
                        
                    
                
                
                    
                        
                            
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
            
        
    
    
    
        
            
                
                    
                    
                
                
                    
                        
                        
                            
                                
                            
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
                    
                        
                    
                
                
            
        
    








         
             
        
    
    
    
         
             
        
    

b、在spring.handlers和spring.schemas写入DubboNamespaceHandler和dubbo.xsd。

其中,DubboNamespaceHandler的内容是:

/*
* Copyright 1999-2011 Alibaba Group.
*  
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*  
*      http://www.apache.org/licenses/LICENSE-2.0
*  
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.config.spring.schema;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.AnnotationBean;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.config.spring.ServiceBean;

/**
* 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自定的标签分别进行了解析。其中,service标签就生成了ServiceBean类,而reference就生成了ReferenceBean类。

3、看ReferenceBean类

public class ReferenceBean extends ReferenceConfig implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean
ReferenceBean是实现了FactoryBean接口的类,我们知道,Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean,这两种Bean都被容器管理,但工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该FactoryBean的getObject方法所返回的对象。
所以,查看ReferenceBean的getObject()方法,

 public Object getObject() throws Exception {
        return get();
    }

    public synchronized T get() {
        if (destroyed){
            throw new IllegalStateException("Already destroyed!");
        }
        if (ref == null) {
            init();
        }
        return ref;
    }

这里的 return get();就是我们的消费端初始化的开始。

4、看ServiceBean类

public class ServiceBean extends ServiceConfig implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware{}
ServiceBean实现了ApplicationListener接口,其在初始化完成后,会回调onApplicationEvent方法:

    public void onApplicationEvent(ApplicationEvent event) {
        if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
            if (isDelay() && ! isExported() && ! isUnexported()) {
                if (logger.isInfoEnabled()) {
                    logger.info("The service ready on spring started. service: " + getInterface());
                }
                export();
            }
        }
    }

这个方法就是服务端发布服务的开始。

5、附上eclipse不识别dubbo标签的解决办法

https://blog.csdn.net/agony_sun/article/details/76853087

你可能感兴趣的:(spring解析dubbo标签)