Prefacio
En la sección anterior descifrado de primavera: análisis de etiquetas predeterminadas, nos centramos en analizar cómo los revistas de primavera las etiquetas predeterminadas. Entonces, este capítulo continúa explicando el análisis de la etiqueta, centrándose en cómo analizar las etiquetas personalizadas. Sin más preámbulos, echemos un vistazo a la introducción detallada.
Etiquetas personalizadas
Antes de explicar el análisis de etiquetas personalizado, consulte cómo personalizar las etiquetas
Definir archivo XSD
Definir un archivo XSD para describir el contenido de componentes
<? xml versión = "1.0" encoding = "utf-8"?> <xsd: schema xmlns = "http://www.battcn.com/schema/battcn" xmlns: xsd = "http://www.ww3.org/2001/xmlschema" xmlns: beans = "http://www.springframework.org/schema/beans" targetNamespace = "http://www.battcn.com/schema/battcn" elementformDefault = "calificado" attribureDefault = "no calificado"> <xsd: import namespace = "http://www.springframework.org/schema/beans"/> <xsd: elemento name = "aplicación"> <xsd: complextype> <xsd: complejContent> <xsd: extension base = "beans: identificados de tipo" </xsd: extensión> </xsd: complejContent> </xsd: complextype> </xsd: elemento> </xsd: esquema>
Definir reglas de análisis
1. Cree una clase para implementar la interfaz BeanDefinitionParser (también puede heredar las clases proporcionadas por Spring) para analizar las definiciones y las definiciones de componentes en el archivo XSD.
Public Class ApplicationBeanDefinitionParser extiende AbstractSingleBeanDefinitionParser {@Override Class GetBeanClass (Element Element) {// El tipo de objeto recibido es como: String name = (String) context.getBean ("Battcn"); return string.class; } @Override protegido void doparse (elemento elemento, beandefinitionBuilder bean) {// El atributo de nombre definido en xsd string name = element.getAttribute ("name"); bean.addConstructorArgValue (nombre); }}Aquí hay una aplicación BeanDefinitionParser que herede los abstractssingleBeanDefinitionParser (es una subclase de BeanDefinitionParser). El enfoque es anular doparse, analizar las etiquetas XML en él y luego inyectar el valor analizado (Levin) en el constructor.
2. Cree una clase para heredar la clase de abstracto de SpaceHandLerSupport
Public Class BattCnNamesPaceHandler extiende NamespaceHandLersUpport {@Override public void init () {RegisterBeanDefinitionParser ("Aplicación", nueva AplicaciónBeAnDefinitionParser ()); }} La función de BattCnNamespaceHandler es muy simple, lo que es decirle al contenedor de primavera que la etiqueta <battcn:application /> debe ser analizada por ese analizador (aquí personalizamos: ApplicationBeanDefinitionParser), que es responsable de registrar componentes en el contenedor de primavera.
3. Escribe los archivos de Spring.Handlers y Spring.Schemas
El directorio donde se almacena el archivo se encuentra en el nombre de recursos/metainf/archivo
Spring.Handlers
http/: //www.battcn.com/schema/battcn=com.battcn.handler.battcnnamespacehandler
Spring.Schemas
http/: //www.battcn.com/schema/battcn.xsd=battcn.xsd
4. Use etiquetas personalizadas
Declare el archivo bean.xml, definido de la siguiente manera
<? xml versión = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" "" "" xmlns: battcn = "http://www.battcn.com/schema/battcn" xsi: schemalocation = "http://www.springframework.org/schema/Beans http://www.springframework.org/schema/Beans/Spring-Beans-Beans-Beans-Beans-Beans.xsping-Beanss.xsping-Beanss.xsping-Beanss.xsping-Beanss.xssping-Beanss.xssping-Beanss.xssping-Beanss.xsping-Beanss.xsping-Beanss.xssping-Beanss.xsping-Beanss.xsping-Beanss.xsping-Beanss.xsping-Beanss.xssper http://www.battcn.com/schema/battcn http://www.battcn.com/schema/battcn.xsd "> <battcn: aplicación id =" Battcn "name =" Levin "/> </Beans>
Crea una clase de prueba. Si ve la palabra Levin de salida de la consola, significa que la etiqueta personalizada es normal.
Aplicación de clase pública {public static void main (String [] args) {applicationContext context = new classpathxmlaPlaPlicationContext ("bean.xml"); String name = (string) context.getBean ("Battcn"); System.out.println (nombre); }}5. Como se muestra en la figura
Análisis del código fuente
Portal de resolución de etiquetas personalizado
public class BeandefinitionParserDelegate {@nullable public beandefinition ParSecustomElement (elemento ELE, @nullable Beandefinition ContainsBd) {// Obtenga la dirección de espacio de nombres http://www.battcn.com/schema/Battcn String Namespaceuri = getnamespaceuri (ele);; if (namespaceuri == null) {return null; } // NamespaceHandler es la aplicación registrada en el controlador de nombres BattcnamespaceHandler personalizado = this.readerContext.getNamesPaceHandlerResolver (). Resolve (NamesPaceUri); if (handler == null) {error ("No se puede ubicar el espacio de nombres de primavera para el espacio de nombres de esquema XML [" + namespaceuri + "]", ele); regresar nulo; } return handler.parse (ele, nuevo parsercontext (this.readerContext, this, conteningbd)); }} Al igual que las reglas de resolución de etiqueta predeterminadas, el espacio de nombres se obtiene a través de getNamespaceURI(Node node) . Entonces, ¿dónde está this.readerContext.getNamespaceHandlerResolver() obtenido? Hacemos un seguimiento del código y podemos encontrar que cuando comience el proyecto, todo el contenido del archivo metainf/spring.handles se analizará en el XMLBeanDefinitionReader y se almacenará en Handlermappers (un concurrientehmap). Cuando se llama a resolve(namespaceUri) para verificar, el contenido almacenado en caché se extraerá para comparar.
clase pública xmlBeanDefinitionReader {public NamespaceHandlerResolver getNamespaceHandlerResolver () {if (this.namespaceHandlerResolver == null) {this.namespaceHandlerResolver = createfaultnamespaceHandlerResolver (); } devolver esto.namespaceHandlerResolver; }}resolver
1. Cargue el mapa de SpaceHandler especificado, y el espacio de nombres extraído se almacena en caché y luego regresa
Clase pública DefaultNamesPaceHandlerResolver {@Override @nullable public NamespaceHandler resolve (String NamesPaceuri) {MAP <String, Object> HandLermAppings = GetHandLermAppings (); // extraer HandlerOrClassName de HandlermAppings Object HandlerOrClassName = HandLermAppings.get (NamesPaceUri); if (handlerOrClassName == null) {return null; } else if (handlerOrClassName instanceOf namespaceHandler) {return (namespaceHandler) handlerOrClassName; } else {String className = (String) HandlerOrClassName; intente {class <?> handlerClass = classUtils.forname (classname, this.classLoader); if (! NamespaceHandler.class.isassignableFrom (HandlerClass)) {Throw New FatalBeanException ("class [" + className + "] para el espacio de nombres [" + Namespaceuri + "] no implementa el [" + NamespaceHandler.class.getName () + "] interfaz"); } // Encuentre la información correspondiente basada en el espacio de nombres en el espacio de nombres de nombrespaceShandler = (NamespaceHandler) BeanUtils.instantiateclass (HandlerClass); // Handler Inicializar NamespaceHandler.init (); handlermappings.put (NamespaceUri, NamespaceHandler); devolver el espacio de nombres; } Catch (ClassNotFoundException ex) {Throw New FatalBeanException ("NamespaceHandler class [" + classame + "] para el espacio de nombres [" + Namespaceuri + "] no encontrado", ex); } Catch (LinkageError err) {tirar nueva fatalBeanException ("Clase no válida de espacio de nombres [" + classname + "] para el espacio de nombres [" + namespaceuri + "]: problema con el archivo de clase del controlador o la clase dependiente", err); }}}}Análisis de etiquetas
Después de cargar el espacio de nombres, el BattCnNamespaceHandler se ha inicializado, y el BattCnNamespaceHandler también llama init() para completar el trabajo de inicialización. Por lo tanto, continuaré ejecutando este código: handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); Solución de etiqueta específica.
Public Class NamespaceHandLersUpport {@Override @nullable public beandefinition Parse (elemento elemento, Parsercontext Parsercontext) {beandefinitionParser Parser = findParserForElement (elemento, parsercontext); return (parser! = null? Parser.parse (elemento, parsercontext): null); } @Nullable private beandefinitionParser findParserForElement (elemento elemental, parsercontext Parsercontext) {// LAGA LA APLICACIÓN LocalName en <Battcn: Application /> .GetDelegate (). GetLocalName (elemento); BeandefinitionParser parser = this.parsers.get (localName); if (parser == null) {parsercontext.getReaderContext (). fatal ("no puede localizar beandefinitionParser para elemento [" + localName + "]", elemento); } return Parser; }}En pocas palabras, es encontrar la instancia AplicationBeanDefinitionParser de los analizadores y llamar a su propio método doparse para un análisis posterior. Finalmente, es la misma rutina de analizar la etiqueta predeterminada ...
Resumir
Después de unos pocos otoño, invierno, primavera y verano desconocidos, todo seguirá la dirección que desee ...
De acuerdo, lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.
Di algo
Código de texto completo: https://gitee.com/battcn/battcn-spring-source/tree/master/chapter2