Analyse des balises personnalisées et enregistrement des Beans dans l'analyse du code source Spring

Auparavant, nous avons dégradé l'analyse des balises par défaut dans Spring. Ci-dessous, nous présentons l'analyse des balises personnalisées pour Beans. Pourquoi Spring est si puissant, c'est qu'il a une forte évolutivité. Par conséquent, nos balises personnalisées peuvent également être analysées par Spring, comme Dubbo. L'analyse des balises personnalisées est également déléguée à BeanDefinitionParserDelegate. La méthode appelée est: parseCustomElement (Element ele). Le code source est le suivant:

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));
}

L'analyse des balises personnalisées via le code ci-dessus est effectuée via une instance NamespaceHandler . Tout d'abord, examinons la définition de NamespaceHandler comme suit:

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

Le NamespaceHandler analyse l'étiquette et renvoie l'étiquette à une instance de Beandefinition ou à une instance de BeanDefinitionHolder . Voici l' implémentation de NamespaceHandler pour la résolution d'étiquettes personnalisée fournie par Spring :

L'acquisition de NamespaceHandler est effectuée par DefaultNamespaceHandlerResolver, qui est similaire au mécanisme SPI. Il charge tous les gestionnaires de META-INF / spring.handlers , les instancie et les met en cache dans Map. Voici la configuration de 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 nous voulons implémenter notre propre NamespaceHandler, nous devons seulement hériter de NamespaceHandlerSupport, qui est plus simple et n'a besoin que d'implémenter la méthode init, et d'initialiser notre analyseur d'étiquettes personnalisé dans la méthode init. Le ContextNamespaceHandler fourni par Spring gère l'espace de noms de contexte comme suit:

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());
    }
}

Nous n'entrerons pas dans les détails ici. Ceux qui sont intéressés peuvent lire le code source par eux-mêmes. Afin d'approfondir la compréhension de l'analyse d'étiquettes personnalisées, écrivons un exemple d'analyse d'étiquettes personnalisées. Ici, nous introduisons d'abord l'utilisation de l'analyseur de balises BeanDefinitionParser, qui est utilisé pour analyser les balises dans la configuration de Spring. Si vous souhaitez analyser les balises personnalisées, nous devons implémenter certaines méthodes en fonction de la situation. Voici quelques implémentations de BeanDefinitionParser, nous n'avons besoin d'hériter que selon nos propres besoins Une seule méthode:

Tout d'abord, nous devons définir le fichier de spécification XML, c'est-à-dire le fichier xsd. Si vous ne connaissez pas xsd, vous pouvez Baidu vous-même. Je suis également insatisfait d'une bouteille et une demi-bouteille de sloshing, donc je copie directement la définition dans le document officiel de Spring. La définition est la suivante:

<?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>

Ensuite, vous devez configurer le fichier xsd écrit ci-dessus dans le fichier spring.schemas du répertoire META-INF. Un exemple est le suivant:

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

Ensuite, vous devez écrire un analyseur de balises BeanDefinitionParse. Ici, nous héritons du code de la classe AbstractSingleBeanDefinitionParser comme suit:

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));
        }
    }
}

Après cela, nous devons enregistrer le BeanDefinitionParse personnalisé que nous avons écrit plus tôt au printemps, nous devons donc créer un NamespaceHandler personnalisé , le code est le suivant:

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

Après l'écriture, vous devez configurer MyNamespaceHandler dans le fichier spring.handlers dans le répertoire META-INF. La configuration est la suivante:

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

Jusqu'à présent, notre travail d'analyse des balises personnalisées est terminé, ci-dessous, nous utilisons la configuration xml et testons les balises personnalisées écrites dans le précédent 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: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"));
}

L' instance SimpleDateFormat sera imprimée dans le code ci-dessus. L'analyse de l'étiquette personnalisée de Spring est facile à comprendre, principalement l'écriture de fichiers xsd et l'écriture d'un analyseur d'étiquette personnalisé. De nombreux frameworks tiers intégrés à Spring ont l'implémentation d'une résolution de balises personnalisée, comme Dubbo.

Je suppose que tu aimes

Origine blog.csdn.net/wk19920726/article/details/108828451
conseillé
Classement