Recentemente, olhei para o código -fonte da primavera e de repente me perguntei como a primavera começou a sua própria configuração Web.xml. Dada a habilidade limitada e a primeira vez que li o código -fonte e publiquei um blog, por favor me perdoe se eu não souber o que fazer ~
O IDE que eu uso é Intellij Idea, que é mais fácil ler o código -fonte do que o Myeclipse, e eu gosto muito no fundo preto. Em seguida, o projeto é executado no plug -in MAVEN TOMCAT7. A versão da primavera é 4.3.2.Release.
Se você escreveu uma rede de primavera com configuração de anotação pura, deve saber que precisa herdar uma classe de inicialização para carregar o feijão e, em seguida, nossas funções e feijões personalizados serão carregados nesta classe. Abaixo está um dos meus webinitializadores
@Order (1) classe pública webmvcinit estende abstrateannotationConfigDispatcherservletInitializer {classe protegida <?> [] GetRootConfigClasses () {return } classe protegida <?> [] getServletConfigClassses () {retorna nova classe [] {webconfig.class}; } String protegida [] getServletMappings () {return new String [] {"/"}; } @Override Protected filter [] getServletFilters () {retorna novo filtro [] {new HiddenHttpMethodfilter ()}; }}Primeiro, observe a estrutura da classe AbstractAnnotationConfigDispatcherServletLitializer. Esta também é uma função da IDEA UML. Clique com o botão direito do mouse nos diagramas-mostre diagramas na classe.
Em seguida, clicamos diretamente no AbstractAnnotationConfigDispatcherServletLitializer. Você pode ver que esta classe é muito simples, com apenas quatro métodos. Em seguida, prestamos atenção ao CreateroTapplicationContext ()
@Override Protected webApplicationContext CreaterOpplicationContext () {class <?> [] Configclasses = getRootConfigClasses (); if (! ObjecjectUtils.IsEmpty (configClasses)) {AnoTationConfigWebApplicationContext rootappContext = new AnoTationConfigWebApplicationContext (); rootappContext.register (configclasses); return rootappcontext; } else {return null; }}Esse método significa aproximadamente para obter as classes de raiz enviadas pelo usuário (programador) e depois registrar os grãos. Não é isso que estamos preocupados, mas esse método deve ser executado após a startup, para que possamos procurar com esse método
Sob a idéia, o Ctrl+G pode encontrar um método ou classe para ligar e depois definir o intervalo de pesquisa para projetar e biblioteca
Descobrimos que o método RegisterContextLoaderListener (ServletContext ServletContext) sob abstrateContextLoaderinitializer chama o CreaterOptApplicationContext () da subclasse para obter o WebApplicationContext e continua a encontrar o calotador do registroContetLoadeler (servletContext). Como resultado, verifica -se que é o OnStartup (ServletContext ServletContext) nesta classe. A classe AbstractContextLoaderinitializer está publicada abaixo.
Classe abstrata public abstrateContextLoaderinitializer implementa WebApplicationInitializer { / ** Logger disponível para subclasses* / Logger final protegido = logFactory.getLog (getClass ()); @Override public void OnStartUp (servletContext servletContext) lança servletexception {registercontextloaderListener (servletContext); } /*** Registre um {@link contextLoaderListener} no contexto do servlet fornecido. O * {@code contextLoaderListener} é inicializado com o contexto do aplicativo retornado * do método de modelo {@link #CreaterOpplicationContext ()}. * @param servletContext O contexto do servlet para registrar o ouvinte contra */ protegido void registringContextLoaderListener (servletContext servletContext) {webApplicationContext rootappContext = CRESEROTAPPLICATIONCIONCIONTEXT (); if (rootappContext! = null) {contextLoaderListener ouvinte = novo contextLoaderListener (rootappContext); ouvinte.setContextInitializers (getRootApplicationContextInitializers ()); servletContext.addlistener (ouvinte); } else {Logger.debug ("Nenhum contextLoaderListener registrado, pois" + "CreaterOpplicationContext () não retornou um contexto de aplicativo"); }} /** * Crie o contexto do aplicativo "<strong> root </strong>" a ser fornecido ao * {@code contextLoaderListener}. * <p> O contexto retornado é delegado para * {@link contextLoaderListener#contextLoaderListener (webApplicationContext)} e será * estabelecido como contexto pai para qualquer contexto {@code despacherServlet} aplicativo *. Como tal, normalmente contém serviços de camada média, fontes de dados, etc. * @Return o contexto do aplicativo root, ou {@code null} se um contexto raiz não for * desejado * @see org.springframework.web.servlet.support.abstractLispxtletTetIlitializer */ protegte /** * Especifique os inicializadores de contexto do aplicativo a serem aplicados ao contexto do aplicativo root * com o qual o {@code contextLoaderListener} está sendo criado. * @since 4.2 * @See #CRANEOTAPplicationContext () * @see contextLoaderListener #SetContextInitializers */ protegido ApplicationContextinitializer <?> [] getRootApplicationContextinitializers () {return null; }}Observe que ignoramos a classe abstrata de abstrato abstrataDispatherServletLitializer (consulte o diagrama UML). Esta classe configura principalmente o DispatcheserServlet, que é a implementação do MVC da primavera e outras funções.
Então quem carregará o AbstractContextLoaderinitializer? WebApplicationInitializer já é uma interface e não haverá classe abstrata para chamá -la. Então, tentei pesquisar na interface WebApplicationInitializer. Como grandes projetos como a Spring são definitivamente orientados para a interface, a chamada é geralmente gravada na interface. Em seguida, encontramos a classe SpringServLetContainerinitializer, que implementa a interface ServletContainerInitializer. Essa classe provavelmente significa iniciar todos os aplicativos da Web. Pode -se dizer que esta classe está muito próxima do nosso objetivo. Abaixo está o SpringServletContainerinitializer
@Handlestypes (WebApplicationInitializer.class) classe pública SpringServLeTletContainerInitializer implementa servletContainerInitializer {@Override public void ONSTARTUP (SETCONTENIMATRIMATRIMATRIMIMENTEXCOMPEXCEMCENTEXCOMPENCIMENTEXCOMPENCIMENTEXCIMENTEXCIMENTEXCEMCENTEXCOMPENCIMENTEXCEMENTEXCEMEXCEMENTEXCEIRATIMEX) {inicializaPration); LinkedList <WebApplicationInitializer> (); if (webAppInitializerclasses! = null) {for (class <?> waiclass: webAppInitializerclasses) {// seja defensivo: alguns contêineres de servlet nos fornecem classes inválidas, // não importa o que @Handlestypes diz ... se (! WebApplicationInitializer.class.isassignablefrom (waiclass)) {try {Initializers.add ((webApplicationInitializer) waiclass.newInstance ()); } catch (throwable ex) {tiro novo servletexception ("Falha ao instanciar a classe WebApplicationInitializer", ex); }}}}} if (Initializers.isEmpty ()) {servletContext.log ("sem spring webApplicationInitializer tipos detectados no ClassPath"); retornar; } servletContext.log (Initializers.size () + "Spring WebApplicationInitializers detectados no ClassPath"); AnoTationAWareOrdercomParator.Sort (Inicializadores); para (WebApplicationInitializer Initializer: Initializers) {Initializer.onstartup (servletContext); }}}No último foreach, inicie todos os aplicativos da Web. Portanto, a questão é: quem começará a SpringServletContainerinitializer? A primavera definitivamente não será capaz de iniciá -lo por si só.
No ambiente da web, existem apenas contêineres da web. Podemos fazer um ponto de interrupção em um dos lugares acima e depois depurar (na verdade, podemos depurar completamente = = ao longo do processo, que é preciso e rápido, mas isso não tem o significado de pesquisa, e o cenário ao longo da estrada é muito bom)
Você pode ver o método inicial da classe StandardContext sob o pacote org.apache.catalina.core. Isso já está no escopo do Tomcat, então nosso objetivo foi alcançado. Observe que a interface ServletContainerInitializer não está no pacote da primavera, mas é Javax.Servlet
Eu acho que o TomCat usa a interface ServletContainerInitializer do Javax.Servlet para encontrar as classes que implementam essa interface no contêiner e depois chamam seu OnStartUp e, em seguida, a SpringServleTleNerinitializer da Spring pode iniciar todas as aplicações na web, que contém o webinitializer que escrevemos. Além disso, a segurança da primavera também é configurada com a anotação para implementar o WebApplicationInitializer, portanto a primavera é muito extensível. Vejamos o código -fonte do Tomcat nos próximos dias para entender o mecanismo Tomcat.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.