Por que começar a olhar para o código -fonte da primavera
Escrevo código no meio das carreiras há quase um ano e meio. Eu uso a estrutura da primavera desde que comecei a trabalhar. Embora eu possa usá -lo e construí -lo, muitas vezes não entendo os princípios por trás dele, como: como a primavera controla as transações, como a SpringMVC lida com solicitações e como a AOP é implementada ... isso faz as pessoas se sentirem muito desconfortáveis, então comece a estudar lentamente o código -fonte da primavera enquanto lê o livro !!!
Como visualizar com eficiência o código -fonte
Minha resposta é olhar para o código -fonte com perguntas específicas, caso contrário, é muito fácil ficar preso nos detalhes do código -fonte e você desmaiará. Finalmente, você descobre o que está lendo há muito tempo.
introdução
A Spring é uma estrutura de nível de código aberto que resolve o problema de acoplamento frouxo entre a camada lógica de negócios e outras camadas e integra idéias de programação orientadas para interface em todo o aplicativo do sistema. É também uma das habilidades essenciais no trabalho de Java ...
Como registra o processo de análise do código -fonte da primavera, não vou elaborar o uso detalhado.
Código central
<Depencency> <PuerpId> org.springframework </frugiD> <ArtifactId> Spring-Context </ArtifactId> <versão> 5.0.2.Release </sipers> </dependency>
uso
public class Application {public static void main (string [] args) {beandEfinitionRegistry beanFactory = new DefaultListableBeanFactory (); XMLBeAndEfinitionReader Reader = new XMLBeandEfinitionReader (BeanFactory); ClassPathResource Resource = new ClassPathResource ("bean.xml"); // O ponto de entrada para todo o carregamento de recursos. leitor.loadbeandEfinitions (recurso); }}Descriptografia
DefaultListableBeanFactory é a implementação padrão do registro da primavera e do feijão de carregamento. Pode ser chamado de ancestral em todo o modelo do COI da primavera.
Rastreando o DefaultListableBeanFactory, você pode encontrar os seguintes blocos de código. Qual é o objetivo deste design?
public abstractAUTOWIRECAPABLEBeanFactory () {super (); ignoredEpendEncyInterface (beannameaware.class); ignoredEpendEncyInterface (beanFactoryAWare.class); ignoredEpendEncyInterface (beanclassloadRaWare.class);}Por exemplo, quando houver o atributo B em A, a primavera instanciará automaticamente o atributo B se for encontrado que o atributo b não é instanciado ao obter o atributo A. Esse também é um recurso importante fornecido na primavera. Em alguns casos, B não será inicializado, como a implementação da interface de beannameraware.
A primavera apresenta isso: Quando a montagem automática, ignore a interface de dependência dada, como analisar as dependências de registro de contexto de aplicação por meio de outros métodos, semelhante à injeção de beanfactory por meio do BeanFactoryAware ou a injeção de ApplicationContext através do ApplicationContextAware.
Gerenciamento de recursos
A interface do recurso é usada para gerenciar arquivos, URL, classe de classe e outros recursos. O recurso é responsável por ler o arquivo de configuração, ou seja, encapsular o arquivo de configuração em um recurso e entregá -lo ao XMLBeandEfinitionReader para processamento.
XML Parsing
O XMLBeAndEfinitionReader é uma implementação da leitura, análise e registro de arquivos de recursos de primavera, e devemos nos concentrar nessa classe.
Rastrear reader.loadBeanDefinitions(resource); , podemos ver o seguinte código central (excluir comentários e lançar exceções)
public int loadBeandEfinitions (codedResource codedResource) lança beandefinitionStoreException {try {inputStream inputStream = codedResource.getResource (). getInputStream (); tente {inputSource inputSource = new inputSource (inputStream); if (codedResource.getEncoding ()! = null) {inputSource.setEncoding (codedResource.getEncoding ()); } retorna doloadbeandEfinitions (inputSource, codedResource.getResource ()); } finalmente {inputStream.close (); }}}O código acima realizou uma operação de codificação pela primeira vez, com o objetivo de se preocupar com o problema de codificação no XML
Se você observar cuidadosamente InputSource inputSource = new InputSource(inputStream); , seu nome de pacote é na verdade org.xml.sax, para que possamos concluir que a primavera usa análise de sax e usa o InputSource para decidir como ler arquivos XML.
Finalmente, os dados preparados são passados para a parte real de processamento do núcleo através de parâmetros doLoadBeanDefinitions(inputSource, encodedResource.getResource())
Obtenha documento
1 doLoadBeanDefinitions(inputSource, encodedResource.getResource()); , omitir várias capturas e comentários
Int DoloadBeandEfinitions protegidos (InputSource inputSource, recurso Recurso) lança beandEfinitionStoreException {try {document doc = doloaddocument (inputSource, recurso); Retornar RegisterBeanDefinitions (Doc, Recurso); }} 2. doLoadDocument(inputSource, resource);
documento protegido doloaddocument (inputSource inputSource, recursos de recursos) lança a exceção {return this.documentLoader.loadDocument (inputSource, getentityResolver (), this.errorHandler, getValidationModeForReRce (Resource), isnamespacea ();Primeiro, você pode obter o modo de verificação (DTD ou XSD) do arquivo XML através do getValidationModeForResource. Você pode definir o método de verificação sozinho. Por padrão, Validation_Auto está ativado, ou seja, o modo de verificação é obtido automaticamente. Leia o arquivo XML através do InputStream e verifique se ele contém palavras doctype. Se ele contiver, é DTD, caso contrário, retornará o XSD.
Os padrões comuns de verificação de arquivos XML são:
classe pública xmlValidationModedEtector { /*** indica que a validação do DTD deve ser usada (encontramos uma declaração "Doctype"). */ public static final int validation_dtd = 2; /*** Indica que a validação do XSD deve ser usada (não encontrou a declaração "doctype"). */ public static final int validation_xsd = 3; public int DetectValidationMode (InputStream inputStream) lança IoException {}} Um parâmetro entityResolver está envolvido this.documentLoader.loadDocument .
Public Document LoadDocument (inputSource inputSource, entityResolver entityResolver, errorHandler errorHandler, int validationMode, boolean namespaceaware) lança a exceção {}O que é EntityResolver? Explicação oficial: se um aplicativo SAX precisar implementar o processamento personalizado de entidades externas, ele deverá implementar essa interface e registrar uma instância com a unidade Sax usando o método setentityResolver. Ou seja, para analisar um XML, o SAX lerá primeiro a declaração no documento XML e pesquisará a definição de DTD correspondente de acordo com a declaração, de modo a verificar o documento, as regras de pesquisa padrão (ou seja, download de rede, baixar a definição do DTD por meio do endereço DTD URI declarado por XML) e executar a autenticação. O processo de download é um processo longo e, quando a rede não estiver disponível, um erro será relatado aqui porque o DTD correspondente não foi encontrado.
A função do EntityResolver é que o próprio projeto pode fornecer um método de como encontrar declarações de DTD, ou seja, o programa implementa o processo de busca de DTDs, o que evita encontrar declarações correspondentes através da rede.
3.EntityResolver aceita dois parâmetros:
Resumo Público InputSource Resolveentity (String publicId, String SystemId) lança saxException, IoException;
3.1 Defina o arquivo bean.xml, com o conteúdo da seguinte forma (Modo XSD)
<? xml versão = "1.0" coding = "utf-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http:/wwww.w3 xsi: schemalocation = "http://www.springframework.org/schema/beans.xsd"> </beans>
Analisado para os dois parâmetros a seguir:
3.2 Defina o arquivo bean.xml, com o conteúdo da seguinte forma (modo DTD)
<? xml versão = "1.0" coding = "utf-8"?> <!
Analisado para os dois parâmetros a seguir:
3.3 Spring usa DelegatingEntityResolver para analisar entityResolver
classe pública DelegatingEntityResolver {@Override @Nullable Public inputSource Resolveentity (String publicId, @NullLable String SystemId) lança saxException, ioexception {if (SystemId! = NULL) {if (SystemId.endswith (dtds_suffix) (ret.Dtdrdrds) {se } else if (SystemId.endSwith (xsd_suffix)) {return this.schemaresolver.resolveentity (publicId, SystemId); }} retornar nulo; }}Podemos ver que diferentes analisadores são usados para diferentes modos
Registrar um feijão
Depois de ler a análise de análise XML, continue rastreando o código e veja como a primavera registra informações de feijão com base no documento
public class xmlbeandEfinitionReader {public int RegisterBeandEfinitions (documento doc, recurso de recurso) lança beandefinitionStoreException {// Create DocumentReReader beandefinitionDocumentReader DocumentReader = CreateBeandEfinitionDocumentReader (); // Registre o número de beandefinições antes das estatísticas int countBefore = getRegistry (). GetBeandEfinitionCount (); // Registrar o BEANDefinition DocumentReader.RegisterBeaNDeFinitions (Doc, CreaterAreadeContext (Recurso)); // Registre o número de beandefinições carregadas desta vez retorna getReGistry (). GetBeandEfinitionCount () - countBefore; }}Ao registrar um feijão, use primeiro uma classe BeandEfinitionParserDelegate para determinar se é o espaço para nome padrão. A implementação é determinar se o URI de namespace é igual ao URI padrão:
classe pública beandefinitionparserDelegate {public static final string beans_namespace_uri = "http://www.springframework.org/schema/beans"; public boolean isDefaultNamespace (@NullLable String Namespaceuri) {return (! StringUtils.haslength (nome de nome) || beans_namespace_uri.equals (nome de nome)); }} Rastrear documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); , onde o DOC é convertido através do LoadDocument no bloco de código anterior. O principal objetivo deste método é extrair nós de raiz (feijão)
public class DefaultBeanDefinitionDocumentReader {@Override public void RegisterBeanDefinitions (documento doc, xmlreaderContext readContext) {this.readerContext = ReadContext; logger.debug ("Carregando definições de feijão"); Elemento root = doc.getDocumentElement (); DoregisterbeandEfinitions (raiz); }} Rastrear doRegisterBeanDefinitions(root) e veremos o seguinte fluxo de processamento
Void protegido DoregisterBeandEfinitions (elemento root) {// ... String Profilesp = root.getAttribute (perfil_attribute); // ... // implementação vazia preprocessxml (root); parsebeanndefinitions (root, this.delegate); // implementação vazia postprocessxml (root); this.delegate = pai;}Primeiro, analise o perfil (a maneira mais comum de jogar é que os objetos do feijão inicializados por diferentes perfis são diferentes, para que implementem vários ambientes)
A análise a seguir usa o modo de método do modelo, onde o pré -processamento e o pós -ProcessXML são métodos vazios, para que as subclasses subsequentes possam executar algum processamento antes e após a análise. Basta substituir esses dois métodos.
Analisar e registrar o BeandEfinition, esta parte do código é relativamente simples
public class DefaultBeandEfinitionDocumentReader { / *** Resolva outros nós no nó raiz importar "," Alias "," Bean ". root.getchildnodes (); Delegate.ParsecustomElement (ELE); ImportbeanDefinitionResource (ELE); Nester_beans_element)) {// Recurse DoregisterbeandEfinitions (ELE); Delegate.parsebeanDefinitionElement (ELE); } Catch (BeandEfinitionStoreException Ex) {GetReaderContext (). Delegue o método ParsebeandEfinitionElement da classe BeaNDefinitionParserDelegate para análise de elementos e devolva a instância do Tipo de Tool do Beenfinition Bdholder (incluindo os vários atributos da classe de arquivo de configuração, nome, ID, alias, etc.)
Quando o Bdholder devolvido não estiver vazio, se houver um atributo personalizado no nó filho da etiqueta padrão, o rótulo personalizado será analisado e analisado novamente e, em seguida, BeanDefinitionReaderUtils.registerBeanDefinition(); Registra o BDHolder e envia o evento de registro, informando o feijão de escuta relevante que o registro foi bem -sucedido.
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/chapter1 (download local)