Análisis de etiquetas personalizadas y registro de Beans en Spring Análisis de código fuente

Anteriormente degradamos el análisis de etiquetas predeterminadas en Spring. A continuación presentamos el análisis de etiquetas personalizadas para Beans. La razón por la que Spring es tan poderoso es que tiene una gran escalabilidad. Por lo tanto, nuestras etiquetas personalizadas también pueden ser analizadas por Spring, como Dubbo. El análisis de etiquetas personalizadas también se delega a BeanDefinitionParserDelegate. El método llamado es: parseCustomElement (Element ele). El código fuente es el siguiente:

public BeanDefinition parseCustomElement(Element ele) {
    return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    //获取命名空间
    String namespaceUri = getNamespaceURI(ele);
    //根据命名空间获取一个
    NamespaceHandler handler =  this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        return null;
    }
    //通过NamespaceHandler解析标签
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

El análisis de etiquetas personalizadas a través del código anterior se logra a través de una instancia de NamespaceHandler . Primero, veamos la definición de NamespaceHandler de la siguiente manera:

public interface NamespaceHandler {
    //初始化
    void init();
    //解析元素返回一个BeanDefinition
    BeanDefinition parse(Element element, ParserContext parserContext);
    //解析元素返回一个BeanDefinitionHolder 
    BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);

El NamespaceHandler analiza la etiqueta y devuelve la etiqueta a una instancia de Beandefinition o una instancia de BeanDefinitionHolder . La siguiente es la implementación de NamespaceHandler para la resolución de etiquetas personalizadas proporcionada por Spring :

La adquisición de NamespaceHandler se realiza mediante DefaultNamespaceHandlerResolver, que es similar al mecanismo SPI. Carga todos los Handlers de META-INF / spring.handlers , los instancia y los almacena en caché en Map. La siguiente es la configuración en spring-beans

http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler

 Si queremos implementar nuestro propio NamespaceHandler, solo necesitamos heredar NamespaceHandlerSupport, que es más simple y solo necesita implementar el método init, e inicializar nuestro analizador de etiquetas personalizado en el método init. El ContextNamespaceHandler proporcionado por Spring maneja el espacio de nombres de contexto de la siguiente manera:

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
        registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
	registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
	registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
	registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
	registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
	registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
    }
}

No entraremos en detalles aquí. Aquellos que estén interesados ​​pueden leer el código fuente por sí mismos. Para profundizar la comprensión del análisis de etiquetas personalizadas, vamos a escribir un ejemplo de análisis de etiquetas personalizadas. Aquí primero presentamos el uso del analizador de etiquetas BeanDefinitionParser, que se usa para analizar etiquetas en la configuración de Spring. Si desea analizar etiquetas personalizadas, necesitamos implementar algunos métodos de acuerdo con la situación. Las siguientes son algunas implementaciones de BeanDefinitionParser, solo necesitamos heredar según nuestras propias necesidades Solo un método:

En primer lugar, necesitamos definir el archivo de especificación XML, el archivo xsd. Si no conoce xsd, puede hacerlo usted mismo con Baidu. También estoy insatisfecho con una botella y media botella de sloshing, así que copie directamente la definición en el documento oficial de Spring. La definición es la siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.baidu.com/schema/myns"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:beans="http://www.springframework.org/schema/beans"
    targetNamespace="http://www.baidu.com/schema/myns"
    elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xsd:import namespace="http://www.springframework.org/schema/beans"/>
    <xsd:element name="dateformat">
        <xsd:complexType>
	    <xsd:complexContent>
	        <xsd:extension base="beans:identifiedType">
		    <xsd:attribute name="lenient" type="xsd:boolean" />
		    <xsd:attribute name="pattern" type="xsd:string" use="required" />
		</xsd:extension>
	    </xsd:complexContent>
	</xsd:complexType>
    </xsd:element>
</xsd:schema>

Luego, debe configurar el archivo xsd escrito anteriormente en el archivo spring.schemas en el directorio META-INF. Un ejemplo es el siguiente:

http\://www.baidu.com/schema/myns/myns.xsd=cn/org/microservice/spring/ioc/customized/myns.xsd

Luego debe escribir un analizador de etiquetas BeanDefinitionParse. Aquí heredamos el código de la clase AbstractSingleBeanDefinitionParser de la siguiente manera:

public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    //返回标签要解析成的Bean的Class实例
    protected Class getBeanClass(Element element) {
        return SimpleDateFormat.class;
    }
    //解析元素
    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        // this will never be null since the schema explicitly requires that a
        // value be supplied
        String pattern = element.getAttribute("pattern");
        bean.addConstructorArg(pattern);
        // this however is an optional property
        String lenient = element.getAttribute("lenient");
        if (StringUtils.hasText(lenient)) {
            bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
        }
    }
}

Después de eso, necesitamos registrar el BeanDefinitionParse personalizado que escribimos anteriormente en Spring, por lo que necesitamos crear un NamespaceHandler personalizado , el código es el siguiente:

public class MyNamespaceHandler extends NamespaceHandlerSupport {
    public void init() {
        registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());
    }
}

Después de escribir, debe configurar MyNamespaceHandler en el archivo spring.handlers en el directorio META-INF. La configuración es la siguiente:

http\://www.baidu.com/schema/myns=cn.org.microservice.spring.ioc.customized.MyNamespaceHandler

Hasta ahora, nuestro trabajo de análisis de etiquetas personalizadas se ha completado, a continuación usamos la configuración xml y probamos las etiquetas personalizadas escritas en el anterior de la siguiente manera:

<?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:myns="http://www.baidu.com/schema/myns"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://www.baidu.com/schema/myns 
http://www.baidu.com/schema/myns/myns.xsd">
    <myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true" />
</beans>
public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    System.out.println(context.getBean("defaultDateFormat"));
}

La instancia de SimpleDateFormat se imprimirá en el código anterior El análisis de la etiqueta personalizada de Spring es fácil de entender, principalmente la escritura de archivos xsd y la escritura del analizador de etiquetas personalizado. Muchos marcos de terceros integrados con Spring tienen la implementación de una resolución de etiqueta personalizada, como Dubbo.

Supongo que te gusta

Origin blog.csdn.net/wk19920726/article/details/108828451
Recomendado
Clasificación