Prefácio
Na seção anterior, descriptografia da primavera - análise de tags padrão, focamos em analisar como a mola analisa as tags padrão. Portanto, este capítulo continua a explicar a análise do rótulo, concentrando -se em como analisar tags personalizadas. Sem mais delongas, vamos dar uma olhada na introdução detalhada.
Tags personalizadas
Antes de explicar a análise de tags personalizada, consulte como personalizar tags
Defina o arquivo XSD
Defina um arquivo XSD para descrever o conteúdo do componente
<?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" elementDefault = "qualificado" qualificado ". Namespace = "http://www.springframework.org/schema/beans"/> <xsd: elemento name = "Application"> <xsd: complexType> <xsd: complexContent> <xsd: extension = "Digpleans: identificado" "> <xsd" names: names: " </xsd: extension> </xsd: complexContent> </xsd: complextype> </xsd: element> </xsd: schema>
Definir regras de análise
1. Crie uma classe para implementar a interface BeandEfinitionParser (também pode herdar as classes fornecidas pela primavera) para analisar as definições e definições de componentes no arquivo XSD.
public class ApplicationBeanBeAndEnitionParser estende resumosSingleBeandEfinitionParser {@Override Protected class GetBeanClass (elemento elemento) {// O tipo do objeto recebido é como: string name = (string) context.getBean ("Battcn"); return string.class; } @Override Protected void Doparse (elemento do elemento, beanBuilder bean) {// o atributo de nome definido em xsd string name = element.getAttribute ("name"); bean.addconstructorargvalue (nome); }}Aqui está um ApplicationBeanDefinitionParser que herda os abstratossinglebeanndEfinitionParser (é uma subclasse do BeandEfinitionParser). O foco é substituir o doparse, analisar as tags XML nele e, em seguida, injetar o valor analisado (Levin) no construtor.
2. Crie uma classe para herdar namespacehandlersupport classe abstrata
classe pública BattcnNamesPaceHandler estende o nome de nome do nome do suporte {@Override public void init () {RegisterBeandEfinitionParser ("Application", new ApplicationBeanDefinitionParser ()); }} A função do BattcnNamesPaceHandler é muito simples, que é dizer ao contêiner de mola que a tag <battcn:application /> deve ser analisada por esse analisador (aqui personalizamos: ApplicationBeandEfinitionParser), responsável por registrar componentes no recipiente de primavera.
3. Escreva primavera. Mandidadores e arquivos Spring.Schemas
O diretório onde o arquivo é armazenado está localizado em recursos de recursos/meta-inf/arquivo
Spring.Handlers
http/: //www.battcn.com/schema/battcn=com.battcn.handler.battcnamespacehandler
Spring.Schema
http/: //www.battcn.com/schema/battcn.xsd=battcn.xsd
4. Use tags personalizadas
Declare o arquivo bean.xml, definido da seguinte forma
<? xml versão = "1.0" coding = "utf-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http:/wwww.w3 xmlns:battcn="http://www.battcn.com/schema/battcn" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.battcn.com/schema/battcn http://www.battcn.com/schema/battcn.xsd "> <battcn: Application Id =" Battcn "Nome =" Levin "/> </Beans>
Crie uma classe de teste. Se você vir a palavra Levin de saída do console, significa que o rótulo personalizado é normal.
public class Application {public static void main (string [] args) {ApplicationContext context = new ClassPathXMLApplicationContext ("bean.xml"); Nome da string = (String) context.getBean ("Battcn"); System.out.println (nome); }}5. Como mostrado na figura
Análise do código -fonte
Portal de resolução de tags personalizado
classe pública beandefinitionParserDelegate {@Nullable public beandEfinition ParsecustomElement (elemento ele, @nullable beandefinition if (namespaceuri == null) {return null; } // NamespaceHandler é o aplicativo registrado no BattcnNamespaceHandler de Battcnamendler if (manipulador == null) {Error ("Incapaz de localizar o nome de namespacendler de mola para xml namespace de esquema [" + namespaceuri + "]", ele); retornar nulo; } return handler.parse (ele, novo parserContext (this.readContext, this, contendobd)); }} Como as regras de resolução de tag padrão, o espaço para nome é obtido através do getNamespaceURI(Node node) . Então, onde está obtido this.readerContext.getNamespaceHandlerResolver() ? Rastreamos o código e podemos descobrir que, quando o projeto é iniciado, todo o conteúdo do arquivo meta-inf/spring.handles será analisado no leitor XMLBeandEfinition e armazenado em HandlerMappers (um concorrente). Quando resolve(namespaceUri) é chamada para verificar, o conteúdo em cache será extraído para comparação.
public class XmlBeandEfinitionReader {public NameSpaceHandlerResolver getNamespaceHandLerResolver () {if (this.namespaceHandlerResolver == null) {this.namespaceHandLerResolver = createfaultNamesPaceHandLerResolver (); } return this.namespaceHandlerResolver; }}resolver
1. Carregue o mapa de namespacehandler especificado e o namespacehandler extraído é armazenado em cache e depois retorna
classe pública DefaultNamesPaceHandLerResolver {@Override @NullLable namespaceHandler resolve (string namespaceuri) {map <string, object> handlerMAppings = gethandlerMAppings (); // Extrair HandlerRorClassName From HandlerMAppings Object HandlerorClassName = handlerMAppings.get (namespaceuri); if (HandleRorclassName == null) {return null; } else if (HandlerRorClassName Instância do nome de nome do HandlerorClassName; } else {string className = (String) HandlerorClassName; tente {class <?> handlerclass = classutils.forname (className, this.classloader); if (! namespacehandler.class.isassignablefrom (handlerclass)) {tire o novo fatalbeanException ("classe [" + className + "] para o namespace [" + namespaceuri + "] não implementa o [" + namespaceHandler.class.getname () + "] interface"); } // Encontre as informações correspondentes com base no namespacehandler namespacehandler = (namespaceHandler) beanutils.instantiatiateclass (HandlerClass); // manipulador inicialize namespacehandler.init (); handlermappings.put (namespaceuri, namespacehandler); retornar namespacehandler; } catch (classNotFoundException Ex) {THROW NOVA FATALBEANEXCECTION ("NamespaceHandler Class [" + ClassName + "] para namespace [" + namespaceuri + "] não encontrado", ex); } catch (linkageError err) {tire nova fatalbeanException ("namespacehandler inválido classe [" + className + "] para namespace [" + namespaceuri + "]: problema com o arquivo da classe manipuladora ou classe dependente", err); }}}}Análise de tags
Depois de carregar o namespacehandler, o BattcnNamesPaceHandler foi inicializado e o BattcnNamesPaceHandler também chama init() para concluir o trabalho de inicialização. Portanto, continuarei a executar este código: handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); solução de tag específica.
classe pública 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 do elemento, parserContext parserContext) {// Aplicar o aplicativo String LocalName em <Battcn: Application /> .getDelegate (). GetLocalName (element); Beandefinitionparser parser = this.parsers.get (localName); if (parser == null) {parserContext.getReRerContext (). FATAL ("Não é possível localizar beandefinitionParser para elemento [" + localName + "]", elemento); } retornar o analisador; }}Simplificando, é para encontrar a instância ApplicationBeandEfinitionParser da Parsers e chamar seu próprio método Doparse para análises adicionais. Finalmente, é a mesma rotina de analisar a tag padrão ...
Resumir
Depois de alguns outono desconhecido, inverno, primavera e verão, tudo seguirá a direção que você deseja ...
Ok, o acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.
Dizer algo
Código de texto completo: https://gitee.com/battcn/battcn-spring-source/tree/master/chapter2