dubbo-config-spring自定义xml标签扩展

 

  要实现自定义自定义标签扩展,需要有如下步骤(在spring中定义了两个接口NamespaceHandler、BeanDefinitionParser,用来实现扩展)

  1.设计配置属性和JavaBean,编写XSD文件;

  2.NamespaceHandler注册一堆BeanDefinitionParser,利用它们来进行解析;

  3.BeanDefinitionParser用于解析每个element的内容;

  4.编写Spring.handlers和Spring.schemas文件以供Spring读取;Spring默认会加载jar包下的META-INF/spring.handlers文件寻找对应的NamespaceHandler;

 

  Dubbo中Spring扩展就是使用Spring的自定义类型,所以同样也有NamespaceHandler、BeanDefinitionParser

 

  org.apache.dubbo.config.spring.schema.DubboNamespaceHandler

  dubbo-config-spring自定义xml标签扩展

 

  org.apache.dubbo.config.spring.schema.DubboBeanDefinitionParser

  dubbo-config-spring自定义xml标签扩展

 

 

   org.apache.dubbo.config.spring.schema.DubboNamespaceHandler#init,该方法用于注册BeanDefinitionParser的实现类,DubboBeanDefinitionParser把不同的配置分别转化成Spring容器中的Bean对象(Config对象);

@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("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));
    registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
    registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
}

  

  对应的Bean

  dubbo-config-spring自定义xml标签扩展

 

  在Spring启动解析相应的配置标签时,相应的启动provider发布服务注册服务,而同时让consumer在启动的时候自动订阅发现服务,加入了两个Bean, ServiceBean、ReferenceBean,分别继承ServiceConfig和ReferenceConfig;同时还分别实现了InitializingBean、DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware接口;

 

  InitializingBean:为Bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是实现该接口的类,在初始化Bean的时候会执行该方法;

  DisposableBean :Bean被销毁的时候,spring容器会自动执行destory方法,比如释放资源

  ApplicationContextAware: 实现了这个接口的Bean,当Spring容器初始化的时候,会自动的将ApplicationContext注入进来;

  ApplicationListener :ApplicationEvent事件监听,Spring容器启动后会发一个事件通知;

  BeanNameAware :获得自身初始化时,本身的Bean的id属性;

 

  下面根据Spring提供接口仿写一个自定义xml标签扩展

  BeanDefinitionParser 用于标签解析

/**
 * 用于标签解析
 */
public class BeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    @Override
    protected Class<?> getBeanClass(Element element) {
        return CommonBean.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String id = element.getAttribute("id");
        String beanName = element.getAttribute("beanName");
        String createTime = element.getAttribute("createTime");

        if (StringUtils.hasText(id)) {
            builder.addPropertyValue("id", id);
        }

        if (StringUtils.hasText(beanName)) {
            builder.addPropertyValue("beanName", beanName);
        }

        if (StringUtils.hasText(createTime)) {
            builder.addPropertyValue("createTime", createTime);
        }
    }
}

  

  BeanNamespaceHandler调用标签解析处理

/**
 * 调用标签解析处理
 */
public class BeanNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        // 将节点名与解析类映射,当节点名称为bean,使用BeanDefinitionParser进行解析
        registerBeanDefinitionParser("bean", new BeanDefinitionParser());
    }
}

  

  dubbo-config-spring自定义xml标签扩展

 

  自定义标签配置,需要在META-INF下创建两个默认Spring配置文件来提供支持,一个是spring.schemas,另一个是spring.handlers,前者是为了验证自定义的xml配置文件是否符合要求,后者是定义Spring解析的配置文件

  

  spring.handlers

http\://org.example/schemas/bean=com.example.bean.schema.BeanNamespaceHandler

  

  spring.schemas

http\://org.example/schemas/bean.xsd=META-INF/bean.xsd

  

  定义一个与自定义配置标签相对应的JavaBean,可根据需要是否实现InitializingBean,ApplicationContextAware等接口

public class CommonBean implements InitializingBean, ApplicationContextAware {
    protected String id;
    protected String beanName;
    protected String createTime;
    private transient ApplicationContext applicationContext;

    public String getId() {
        return id;
    }

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

    public String getBeanName() {
        return beanName;
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println(applicationContext.getBeansOfType(this.getClass()));
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public String toString() {
        return "CommonBean{" +
                "id='" + id + '\'' +
                ", beanName='" + beanName + '\'' +
                ", creteTime='" + createTime + '\'' +
                '}';
    }
}

  

  

  创建一个工程进行测试

  在resources目录下创建bean.xml

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:customer="http://org.example/schemas/bean"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://org.example/schemas/bean http://org.example/schemas/bean.xsd">
    <customer:bean />
</beans>

  

  测试类

public class MyTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        context.start();
    }
}

  

 dubbo-config-spring自定义xml标签扩展

 

相关文章: