Происхождение Dubbo, рассказ о механизме расширения Spring XML Schema

Spring
Происхождение Dubbo, рассказ о механизме расширения Spring XML Schema

задний план

В Dubbo вы можете использовать XML для настройки соответствующей информации, а также для импорта или экспорта услуг. После завершения настройки проект запускается, и Spring прочитает файл конфигурации и сгенерирует bean-компоненты, связанные с внедрением. Как Dubbo реализует пользовательский XML для загрузки и чтения Spring?

Механизм расширения Spring XML Schema. Начиная с версии Spring 2.0, Spring предоставляет механизм расширения, основанный на формате схемы XML, для определения и настройки bean-компонентов.

Механизм расширения Spring XML Schema

Реализация расширения Spring XML Schema на самом деле очень проста, просто выполните следующие четыре шага.

  1. Создайте файл XML-схемы, который ниже называется XSD-файлом, поскольку расширение файла — xsd.
  2. Напишите, чтобы реализовать один или несколькоBeanDefinitionParser.
  3. написатьNamespaceHandlerКласс реализации.
  4. регистрNamespaceHandlerи XSD-файлы.

Мы следуем вышеуказанным шагам и, наконец, завершаем Spring анализ следующей конфигурации.

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:demo="http://www.test.com/demo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.test.com/demo http://www.test.com/demo/demo.xsd">

    <demo:application name="test" id="test"/>
</beans>

Создать XSD-файл

Файлы XSD в основном используются для определения формата XML и проверки правильности XML. В среде IDE импортируйте XSD-файл и отредактируйте XML-файл для советов.

Ниже мы создаем файл XSD.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.test.com/demo"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:beans="http://www.springframework.org/schema/beans"
            targetNamespace="http://www.test.com/demo"
            elementFormDefault="qualified"
            attributeFormDefault="unqualified">

    <xsd:import namespace="http://www.springframework.org/schema/beans"/>

    <xsd:element name="application">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="name" type="xsd:string" use="required"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

в приведенном выше файле XSDwww.test.com/demoЭто пользовательский адрес пространства имен, который будет использоваться ниже.

Реализовать BeanDefinitionParser

реализовано здесьBeanDefinitionParser, здесь выполняется фактический анализ действия XML.

Поскольку приведенный выше пример относительно прост, мы можем напрямую наследовать абстрактный класс, предоставляемый Spring.AbstractSingleBeanDefinitionParser, а затем реализовать соответствующие методы.

public class DemoBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    /**

     * 返回最会需要注入 Spring Bean 的类型
     * @param element
     * @return
     */
    @Override
    protected Class<?> getBeanClass(Element element) {
        return DemoApplication.class;
    }

    /***
     * 这个方法完成真正解析动作
     * @param element
     * @param builder
     */
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String name=element.getAttribute("name");
        builder.addPropertyValue("name",name);
    }
}

Конечно, это также может быть реализовано напрямуюBeanDefinitionParser, который является более гибким, но более сложным, чем приведенный выше.

public class BeanApplicationDefinitionParser implements BeanDefinitionParser {

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {

        String name=element.getAttribute("name");
        // Bean 定义,最后根据这个生产 Bean
        RootBeanDefinition rootBeanDefinition=new RootBeanDefinition();
        rootBeanDefinition.setBeanClass(DemoApplication.class);
        rootBeanDefinition.setLazyInit(false);
        // 添加解析的属性
        rootBeanDefinition.getPropertyValues().add("name",name);
        // 将生成的 BeanDefinition 注册,少了这一步将会导致最后生成 Bean 时报错
        parserContext.getRegistry().registerBeanDefinition("application",rootBeanDefinition);
        return rootBeanDefinition;
    }
}

Реализовать обработчик пространства имен

На этом этапе реализуется NamespaceHandler, и разработчики могут настраивать NamespaceHandler до тех пор, пока они наследуютNamespaceHandlerSupportабстрактный класс, реализацияinitметод. В этом методе зарегистрируйте реализацию вышеуказанного шагаBeanDefinitionParser.

public class DemoNameSpaceHandler extends NamespaceHandlerSupport {

    @Override

    public void init() {

        // elementName 为命名空间
        registerBeanDefinitionParser("application",new BeanApplicationDefinitionParser());
    }
}

Зарегистрируйте XSD и NamespaceHandler

На этом шаге нам нужно сгенерировать два файла конфигурации в META-INF, которыеspring.handlers,spring.schemas.

spring.schemasУказывает путь к файлу XSD.

http\://www.test.com/demo/demo.xsd=com/spring/learning/xml/schemas/autoring/leanrn/demo.xsd

spring.handlersуточнитьNamespaceHandlerПолное имя класса, включая предыдущее имя пакета.

Здесь следует отметить, чтонужно сбежать

тестовый забег

Сначала мы создаем файл конфигурации Spring XML.

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:demo="http://www.test.com/demo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.test.com/demo http://www.test.com/demo/demo.xsd">

    <demo:application name="test" id="test"/>
</beans>

Здесь следует отметить, что вам нужно использовать определение в файле XSDhttp://www.test.com/demo.

Затем мы используем SpringBoot, импортируем файл XML и запускаем его.

@SpringBootApplication
@ImportResource(locations = {"classpath:applicationContext.xml"})
public class XmlSchemaApplication {


    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(XmlSchemaApplication.class, args);
        DemoApplication demoApplication=applicationContext.getBean(DemoApplication.class);
        System.out.println("application name is "+demoApplication.getName());
    }
}

Результат:

output
application name is test

Исследование исходного кода механизма расширения Spring XML

Здесь мы в основном изучаем, как Spring загружает пользовательские файлы расширения XML.

Во время процесса запуска Spring он будет проходить черезBeanDefinitionDocumentReaderПрочитайте всю конфигурацию в теге beans, этот процесс будет проходитьBeanDefinitionParserDelegate#parseCustomElementРазобрать пользовательские элементы.

carbon34.png

Вышеупомянутый процесс синтаксического анализа может быть настроенNamespaceHandler, затем позвонитеparseРазбор метода.

Затем мы смотрим наNamespaceHandlerResolver#resolveметод, узнайте, как получить пользовательскийNamespaceHandler.

carbon35.png

В этом методе основноеhandlerMappingsполучить из кешаNamespaceHandler. И кеш исходит отgetHandlerMappingsметод, этот метод загрузит наш пользовательский вышеspring.handlersдокумент.

carbon36.png

После прочтения Spring LoadingNamespaceHandlerпроцесс, ниже мы рассмотрим наиболее важныеBeanDefinitionКак сгенерировать.

Как упоминалось выше, Spring будет использоватьNamespaceHandler.parseразбор, так как мы наследуемNamespaceHandlerSupport, смотрите конкретную реализацию внутри.

carbon37.png

carbon38.png

Получение BeanDefinition зарегистрирует его в контейнере, а затем передастBeanDefinitionСгенерировать бобы. Этот процесс генерации не относится к содержанию этой главы, поэтому он больше не описывается, и заинтересованные студенты могут искать самостоятельно.

Реализация расширения XML-схемы Dubbo

Наконец, мы рассмотрим, как реализовано расширение Dubbo XML Schema.

image.png

image.png

Видно, что расширение Dubbo XML Schema соответствует четырем стандартным шагам Spring.

Суммировать

Наконец, резюмируйте полный текст с изображением.

SpringXML扩展.png

справочная документация

xsd-custom-registration
Механизм расширения схемы XML в Spring

其他平台.png