задний план
В Dubbo вы можете использовать XML для настройки соответствующей информации, а также для импорта или экспорта услуг. После завершения настройки проект запускается, и Spring прочитает файл конфигурации и сгенерирует bean-компоненты, связанные с внедрением. Как Dubbo реализует пользовательский XML для загрузки и чтения Spring?
Механизм расширения Spring XML Schema. Начиная с версии Spring 2.0, Spring предоставляет механизм расширения, основанный на формате схемы XML, для определения и настройки bean-компонентов.
Механизм расширения Spring XML Schema
Реализация расширения Spring XML Schema на самом деле очень проста, просто выполните следующие четыре шага.
- Создайте файл XML-схемы, который ниже называется XSD-файлом, поскольку расширение файла — xsd.
- Напишите, чтобы реализовать один или несколько
BeanDefinitionParser
. - написать
NamespaceHandler
Класс реализации. - регистр
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());
}
}
Результат:
application name is testИсследование исходного кода механизма расширения Spring XML
Здесь мы в основном изучаем, как Spring загружает пользовательские файлы расширения XML.
Во время процесса запуска Spring он будет проходить черезBeanDefinitionDocumentReader
Прочитайте всю конфигурацию в теге beans, этот процесс будет проходитьBeanDefinitionParserDelegate#parseCustomElement
Разобрать пользовательские элементы.
Вышеупомянутый процесс синтаксического анализа может быть настроенNamespaceHandler
, затем позвонитеparse
Разбор метода.
Затем мы смотрим наNamespaceHandlerResolver#resolve
метод, узнайте, как получить пользовательскийNamespaceHandler
.
В этом методе основноеhandlerMappings
получить из кешаNamespaceHandler
. И кеш исходит отgetHandlerMappings
метод, этот метод загрузит наш пользовательский вышеspring.handlers
документ.
После прочтения Spring LoadingNamespaceHandler
процесс, ниже мы рассмотрим наиболее важныеBeanDefinition
Как сгенерировать.
Как упоминалось выше, Spring будет использоватьNamespaceHandler.parse
разбор, так как мы наследуемNamespaceHandlerSupport
, смотрите конкретную реализацию внутри.
Получение BeanDefinition зарегистрирует его в контейнере, а затем передастBeanDefinition
Сгенерировать бобы. Этот процесс генерации не относится к содержанию этой главы, поэтому он больше не описывается, и заинтересованные студенты могут искать самостоятельно.
Реализация расширения XML-схемы Dubbo
Наконец, мы рассмотрим, как реализовано расширение Dubbo XML Schema.
Видно, что расширение Dubbo XML Schema соответствует четырем стандартным шагам Spring.
Суммировать
Наконец, резюмируйте полный текст с изображением.
справочная документация
xsd-custom-registration
Механизм расширения схемы XML в Spring