1. Antecedentes
Recientemente, debido a los problemas con el escaneo de paquetes del proyecto, en el proceso de resolver el problema, descubrí accidentalmente que Spring y SpringMVC tienen una relación de contenedores para padres e hijos, y es precisamente por esto que el problema del escaneo de paquetes a menudo ocurre. Aquí analizamos y entendemos la relación de contenedores matriz entre Spring y SpringMVC y brindamos la forma oficial recomendada de escaneo de paquetes en archivos de configuración Spring y SpringMVC.
2. Concepto comprensión y conocimiento que colocan los cimientos
En el concepto central del marco general de Spring, los contenedores son la idea central, que se utiliza para gestionar todo el ciclo de vida de un frijol. En un proyecto, no necesariamente hay un solo contenedor. La primavera puede incluir múltiples contenedores, y el contenedor tiene niveles superiores e inferiores. El escenario más común en la actualidad es introducir los dos marcos de Spring y SpringMVC en un proyecto. Entonces en realidad son dos contenedores. Spring es un contenedor padre y SpringMVC es su contenedor infantil. El frijol registrado en el contenedor principal de primavera es visible para el contenedor SpringMVC, mientras que el frijol registrado en el contenedor SpringMVC es invisible para el contenedor principal de Spring, es decir, el contenedor infantil puede ver el frijol registrado en el contenedor principal, de lo contrario no funcionará.
Podemos usar la configuración de anotación unificada de la siguiente manera para registrar por lotes los frijoles, sin configurar cada bean usando XML por separado.
<contexto: componente-escan-scan-package = "com.hafiz.www" />
Desde el manual de referencia proporcionado por Spring, sabemos que la función de esta configuración es escanear todas las clases en el paquete de paquete base configurado que usa la anotación @Component, y registrarlas automáticamente en el contenedor. Al mismo tiempo, también escanean las tres anotaciones de @Controller, @Service y @Respository porque se heredan de @Component.
En el proyecto, a menudo vemos la siguiente configuración. De hecho, con la configuración anterior, esto se puede omitir, porque la configuración anterior activará la siguiente configuración de forma predeterminada. La siguiente configuración declarará las anotaciones como @Required, @aUtowired, @PostConstruct, @PersistenceContext, @Resource, @Predestroy, etc. de forma predeterminada.
<Contexto: anotación-config/>
Además, hay otra configuración relacionada con SpringMVC. Después de la verificación, esto debe configurarse para SpringMVC porque declara @RequestMapping, @RequestBody, @ResponseBody, etc. Además, esta configuración carga muchos métodos de enlace de parámetros de forma predeterminada, como el analizador de conversión JSON.
<MVC: impulsado por anotación />
La versión de configuración de la oración anterior antes de Spring 3.1 es equivalente al siguiente método de configuración
<
La versión después de Spring3.1 es equivalente a los siguientes métodos de configuración
<
3. Análisis de escenarios específico
Echemos un vistazo más de cerca a las causas del conflicto del contenedor entre Spring y SpringMVC.
Tenemos dos contenedores, Spring y SpringMVC, y sus archivos de configuración son ApplicationContext.xml y ApplicationContext-Mvc.xml respectivamente.
1. El <contexto: componente-scan base-paquete = "com.hafiz.www" /> está configurado en ApplicationContext.xml para ser responsable de escanear y registrar todos los frijoles que deben registrarse.
2. Configurar <mvc: anotación dirigida /> en applicationContext-MVC.XML para ser responsable del uso de anotaciones relacionadas con SpringMVC.
3. Al comenzar el proyecto, descubrimos que SpringMVC no podía saltar. Establecemos el nivel de impresión de registro del registro para depurar para la depuración. Descubrimos que las solicitudes en el contenedor SpringMVC no parecían estar asignadas al controlador específico.
4. Configurar <context: componente-scan base-pakage = "com.hafiz.www" /> en ApplicationContext-Mvc.xml. Después de reiniciar, la verificación es exitosa y el salto SpringMVC es válido.
Verifiquemos la razón específica, veamos el código fuente y comencemos desde el despachador de SpringMVC para buscar hacia abajo. Descubrimos que cuando se inicialice SpringMVC, buscaremos todos los frijoles en el contenedor SpringMVC que usan la anotación @Controller para determinar si es un controlador. La configuración de dos pasos de 1 y 2 hace que el contenedor SpringMVC actual no registre el bean con la anotación @Controller, pero todos los frijoles con la anotación @Controller están registrados en el contenedor principal de la primavera, por lo que SpringMVC no puede encontrar el procesador y no puede saltar. El código fuente central es el siguiente:
protegido inithandlermethods () {if (logger.isdebugeNabled ()) {logger.debug ("Buscando asignaciones de solicitudes en el contexto de la aplicación:" + getApplicationContext ()); } String [] beanNames = (this.detEtThandLermethodsinancEstorcontexts? BeanFactoryUtilss.BeanNamesFortypeCludeDancEns (getApplicationContext (), Object.Class): GetApplicationContext (). GetBeanNamesfortype (Object.ClassSs)); for (string beanName: beanNames) {if (isHandler (getApplicationContext (). GetType (BeanName))) {DetEdThandLermethods (BeanName); }} handlermethodsinitialized (gethandlermethods ());}En el método isHandler, determinaremos si la anotación del bean actual es un controlador. El código fuente es el siguiente:
boolean boolean protegido (clase <?> beantype) {return anotationUtils.findannotation (beantype, controler.class)! = null;}En la configuración del cuarto paso, todos los frijoles con anotación @Controller también se registran en el contenedor SpringMVC, por lo que SpringMVC puede encontrar el procesador para el procesamiento, por lo que salta normalmente.
Encontramos la razón por la que no puede saltar correctamente, entonces, ¿cuál es su solución?
Notamos que en el método inithandlermethods (), el interruptor detectthandlermethodsinancestorcontexts, controla principalmente qué frijoles en el contenedor se obtienen y si el contenedor principal está incluido. No está incluido por defecto. Por lo tanto, la solución es configurar la propiedad DetecThandLermethodsinancEnContexts de Handlermapping a True en el archivo de configuración de SpringMVC (aquí necesita ver qué tipo de HandLermapping se usa de acuerdo con el proyecto específico), para que pueda detectar el frijol del contenedor principal. como sigue:
<Bean> <Property name = "DetEdLermethodsInancEstorcontexts"> <value> true </alue> </property> </bean>
Sin embargo, en proyectos reales, habrá muchas configuraciones. Dividamos diferentes tipos de frijoles en diferentes contenedores de acuerdo con las recomendaciones oficiales de acuerdo con diferentes módulos comerciales: el contenedor primario de primavera es responsable del registro de todos los demás frijoles que no están anotados por @Controller, mientras que SpringMVC solo es responsable del registro de frijoles anotados por @Controller, por lo que cada uno asume sus propias responsabilidades y aclarar límites. El método de configuración es el siguiente
1.Configure en ApplicationContext.xml:
<
2. Configuración en ApplicationContext-Mvc.xml
<
3. Resumen
De esta manera, después de haber entendido la relación de los contenedores para padres e hijos entre Spring y SpringMVC y el principio de escaneo y registro, según las sugerencias oficiales, podemos asignar diferentes tipos de frijoles a diferentes contenedores para la gestión. Si no se pueden encontrar problemas como el bean, SpringMVC no se puede redirigir y la configuración de la transacción falla, podemos localizar rápidamente y resolver el problema. Muy feliz, ¿hay alguna ~
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.