Préface
Dans la section précédente décryptage de printemps - Analyse des balises par défaut, nous nous concentrons sur l'analyse de la façon dont Spring analyse les balises par défaut. Donc, ce chapitre continue d'expliquer l'analyse de l'étiquette, en se concentrant sur la façon d'analyser les balises personnalisées. Sans plus tarder, jetons un coup d'œil à l'introduction détaillée.
Tags personnalisés
Avant d'expliquer l'analyse des balises personnalisées, veuillez voir comment personnaliser les balises
Définir le fichier XSD
Définissez un fichier XSD pour décrire le contenu des composants
<? xml version = "1.0" Encoding = "utf-8"?> <xsd: schema xmlns = "http://www.battcn.com/schema/battcn" xmlns: xsd = "http://www.w3.org/2001/xmlschema" xmlns: beans = "http://www.springframework.org/schema/beans" TargetNamespace = "http://www.battcn.com/schema/battcn" elementFormDefault = "Qualified" attributeFormDefaul namespace = "http://www.springframework.org/schema/beans" /> <xsd: élément name = "application"> <xsd: complexType> <xsd: complexContent> <xsd: extension Base = "beans: identifiedType"> <xsd: attribute name = "name" type = "xsd: strime". </ xsd: extension> </ xsd: complexContent> </ xsd: complexType> </ xsd: élément> </xsd: schéma>
Définir les règles d'analyse
1. Créez une classe pour implémenter l'interface BeanDefinitionParser (peut également hériter des classes fournies par Spring) pour analyser les définitions et les définitions des composants dans le fichier XSD.
La classe publique ApplicationBeAndeFinitionParser étend AbstractSingleBeAndeFinitionParser {@Override Protected class GetBeAnClass (élément élément) {// Le type de l'objet reçu est tel que: String name = (String) context.getBean ("Battcn"); return String.class; } @Override Protected void doparse (élément élément, beanDefinitionBuilder bean) {// L'attribut de nom défini dans xsd String name = element.getAttribute ("name"); bean.addConstructorArgValue (nom); }}Voici une application BEADEFINITIONPARSER qui hérite de résumer AbstractSingleBeAnDefinitionParser (est une sous-classe de BeanDefinitionParser). L'objectif est de remplacer le doparse, d'analyse les balises XML, puis d'injecter la valeur analysée (Levin) dans le constructeur.
2. Créez une classe pour hériter
classe publique BattCnNamespaceHandler étend des noms de nomshandlersupport {@Override public void init () {registerBeAnDeFinitionParser ("application", new ApplicationBeAndeFinitionParser ()); }} La fonction de BattCnNamesPaceHandler est très simple, ce qui est de dire au conteneur à ressort que la balise <battcn:application /> doit être analysée par cet analyseur (ici nous personnalisés: ApplicationBeAndeFinitionParser), qui est responsable de l'enregistrement des composants du conteneur de ressort.
3. Écrivez Spring.Handlers et Spring.schemas Fichiers
Le répertoire où le fichier est stocké est situé en ressources / méta-infr / nom de fichier
printemps.
http /: //www.battcn.com/schema/battcn=com.battcn.handler.battcnnamespacehandler
Spring.schemas
http /: //www.battcn.com/schema/battcn.xsd=battcn.xsd
4. Utilisez des balises personnalisées
Déclarez le fichier bean.xml, défini comme suit
<? 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: battcn = "http://www.battcn.com/schema/battcn" xsi: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/bans/www.springframework.org/schema/bans/www.springframework.org/schema/bans/www.springframework.org/schema/Beans/www.spring http://www.battcn.com/schema/battcn http://www.battcn.com/schema/battcn.xsd "> <battcn: application id =" battcn "name =" levin "/> </ Beans>
Créer une classe de test. Si vous voyez le mot de sortie de la console, cela signifie que l'étiquette personnalisée est normale.
Application de classe publique {public static void main (String [] args) {applicationContext context = new ClassPathXmlApplicationContext ("bean.xml"); String name = (String) context.getBean ("BattCn"); System.out.println (nom); }}5. Comme indiqué sur la figure
Analyse du code source
Portail de résolution de balise personnalisé
Classe publique BeanDefinitionParserDelegate {@Nullable public BeanDefinition PARSECUSUMEMENT (élément ele, @nullable beandefinition contientbd) {// Obtenez l'adresse de l'espace de noms http://www.battcn.com/schema/battcn string namespaceuri = getNamespaceuri (ele); if (namespaceuri == null) {return null; } // namespaceHandler est l'application enregistrée dans le mannequin BattCnNamesPaceHandler Handler = this.readerContext.GetNamesPaceHandlerresolver (). Resolve (namespaceuri); if (handler == null) {error ("Impossible de localiser Spring NamespaceHandler pour XML Schema Namespace [" + namespaceuri + "]", ele); retourner null; } return handler.parse (ele, new ParserConText (this.readerContext, this, contenantbd)); }} Comme les règles de résolution de balises par défaut, l'espace de noms est obtenu via getNamespaceURI(Node node) . Alors, où est this.readerContext.getNamespaceHandlerResolver() obtenu? Nous suivons le code et nous pouvons constater que lorsque le projet commencera, tous les contenus de fichiers Meta-Inf / Spring. Lorsque resolve(namespaceUri) est appelée pour vérifier, le contenu en cache sera extrait pour comparaison.
classe publique xmlBeAndeFinitionReader {public namespacehandlerresolver getNamespaceHandlerresolver () {if (this.namespacehandlerresolver == null) {this.namespacehandlerresolver = createfaultNamespaceHandlerSolver (); } return this.NamespaceHandlerresolver; }}résoudre
1. Chargez la carte spécifiée de l'espace-hancheur, et l'espace-handler extrait est mis en cache, puis retourne
classe publique defaultNamespaceHandlerresolver {@Override @nullable public namespaceSpaceHandler Resolve (String namespaceuri) {map <string, object> handlerMappings = gethandlerMappings (); // Extraire HandlerorClassName à partir 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; essayez {class <?> handlerclass = classutils.forname (className, this.classloader); if (! namespacehandler.class.isassignableFrom (handlerclass)) {throw new FatalBeanException ("class [" + classname + "] pour namespace [" + namespaceuri + "] n'implémente pas l'interface [+ namespace-handler.class.getname () +"] interface "); } // Trouvez les informations correspondantes basées sur l'espace de noms namespacehandler namespacehandler = (namespacehandler) beanutils.instantiateclass (handlerclass); // Handler Initialize namespaceHandler.init (); handlerMappings.put (namespaceuri, namespacehandler); return namespaceHandler; } catch (classNotFoundException ex) {throw new FatalBeanException ("namespaceHandler class [" + classname + "] for namespace [" + namespaceuri + "] non trouvé", ex); } catch (LinkageError ERR) {Throw New FatalBeanException ("Invalid namespaceHandler class [" + className + "] for namespace [" + namespaceuri + "]: problème avec le fichier de classe de gestion ou la classe dépendante", err); }}}}Analyse des tags
Après avoir chargé le namespacehandler, le BattCnNamespaceHandler a été initialisé et le BattCnNamesPaceHandler appelle également init() pour terminer le travail d'initialisation. Par conséquent, je continuerai à exécuter ce code: handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); Solution de balise spécifique.
classe publique namespaceHandlersupport {@Override @nullable public beanDefinition parse (élément élément, parserContext ParserContext) {beanDefinitionParser parser = findParserForElement (élément, ParserConText); return (analyser! = null? Parser.parse (élément, parserContext): null); } @Nullable privé beandeFinIitionParser findSParserForElement (élément élément, ParserContext ParserContext) {// analyse la chaîne d'application localName dans <Battcn: application /> .getdelegate (). GetLocalName (élément); BeanDefinitionParser parser = this.parsers.get (LocalName); if (parser == null) {ParserConText.GetReaderConText (). Fatal ("Impossible de locales beanDefinitionParser pour élément [" + localName + "]", élément); } Retour analyseur; }}En termes simples, il s'agit de trouver l'instance ApplicationBeanDeFinitionParser à partir d'analyseurs et d'appeler sa propre méthode doparse pour une analyse plus approfondie. Enfin, c'est la même routine d'analyse de la balise par défaut ...
Résumer
Après quelques personnes, hiver, printemps et été inconnus, tout suivra la direction que vous voulez ...
D'accord, ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.
Dire quelque chose
Code texte complet: https://gitee.com/battcn/battcn-spring-source/tree/master/chapter2