Este artículo es un artículo espejo de traducción automática, por favor haga clic aquí para saltar al artículo original.

Vista: 15336|Respuesta: 0

[Fuente] La excepción se resuelve inyectando la instancia RedisTemplate en SpringBoot

[Copiar enlace]
Publicado en 11/3/2019 13:25:56 | | | |
Recientemente, RedisTemplate se utilizó durante el desarrollo del proyecto, y las pruebas unitarias solicitaron "Field redisTemplate en com.example.demo1.dao.RedisDao requería un bean del tipo 'org.springframework.data.redis.core.RedisTemplate' que no se pudo encontrar", que se traduce como "no se pudo encontrar un bean de tipo RedisTemplate". Por supuesto, solo viendo esta frase, no podemos estar seguros de por qué ocurre este problema. Ahora, publica un registro detallado de errores.

2018-08-10 14:53:49.761 - Detecté la excepción mientras permitía a TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] preparar la prueba instancia [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext
    en org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    en org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    en org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
    en org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
    en org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    en org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    en org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    en org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    en org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    en org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    en org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    en org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    en org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    en org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    en org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    en org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    en org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    en org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    en org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    en org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    en org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    en org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    en org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    en org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    en org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    en org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Causado por: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creando bean con nombre 'redisDao': Dependencia insatisfecha expresada a través del campo ' redisTemplate'; Excepción anidada es org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean calificativo de tipo 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' disponible: se espera al menos 1 bean que califica como candidato a autowire. Anotaciones de dependencias: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    en org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    en org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    en org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    en org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    en org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    en org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    en org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    en org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    en org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    en org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    en org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    en org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    en org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    en org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    en org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    en org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    en org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
    en org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    en org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 25 marcos comunes omitidos
Causado por: org.springframework.beans.factory.NoSuchBeanDefinitionException: No hay bean calificativo de tipo 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' disponible: se espera al menos 1 bean que califica como candidato a autowire. Anotaciones de dependencias: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    en org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
    en org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    en org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    en org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 43 marcos comunes omitidos
Ver este gran registro de errores es un poco mareante, de hecho, solo necesitamos mirar los registros clave para localizar el problema. El segundo Causado por en el registro de errores imprime el registro de errores clave:No hay bean calificativo de tipo 'org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>。

El autor revisa el código escrito y especifica el tipo específico al inyectar RedisTemplate< K, V>.


Según el registro de errores, comprueba el código en la línea 1493 de la clase DefaultListableBeanFactory, el código fuente es el siguiente:

Estos dos métodos muestran que ningún bean puede ser emparejado < RedisTemplate String, Object, >, así que ¿cómo resolver este problema? Puede que quieras usar RedisTemplate< K, V> sin especificar el tipo específico y modificar el código de la siguiente manera:

Reinicia el servicio, no se reporta ningún error en el registro de arranque, y RedisTemplate inyecta el bean con éxito. Me pregunto por qué RedisTemplate< String, Object> inyectar granos falla. Después de pensarlo durante mucho tiempo, pensé que RedisTemplate se configura automáticamente en el framework SpringBoot, y que el valor predeterminado en el contenedor es la instancia de RedisTemplate. Pensando en esto, debes revisar los documentos oficiales de la web para ver si hay alguna explicación en ellos. Efectivamente, la sección 30.1.1 de la documentación oficial sigue explicando RedisTemplate.

Dirección oficial del documento:https://docs.spring.io/spring-bo ... ference/htmlsingle/




Si añades el tuyo propio@Beande cualquiera de los tipos autoconfigurados, reemplaza al predeterminado (excepto en el caso de RedisTemplate, cuando la exclusión se basa en el nombre del bean, redisTemplate, no en su tipo).
Si añades tu propio bean para el tipo de configuración automática, reemplazará al predeterminado. Mi código parece estar bien, espera... Esta frase entre paréntesis es el punto. Traduce una onda,Excepto en el caso de RedisTemplate, cuando se excluye en función del nombre del grano, no de su tipo. El inglés no es muy bueno, y parece que la traducción no es muy fluida.

Ahora parece entenderse que el RedisTemplate< String, Object > se usa @Autowired al inyectarse,@Autowired ensamblado por tipo por defecto。 En otras palabras, si quieres conseguir los granos > RedisTemplate< String, Object, tienes que montarlos según sus nombres. Entonces, naturalmente, piensa en usarlo@Resource, se ensambla por defecto según el nombre。 Modifica el código de nuevo de la siguiente manera:


La anotación ha cambiado de @Autowired a @Resource ¡El proyecto comenzó sin errores y se resolvió perfectamente!

Reinicia el servicio de nuevo, el registro de inicio no informa de error y el RedisTemplate< String, Object> inyecta el bean con éxito. A través de este error, aprendí una función de la clase de auto-configuración en el framework SpringBoot. Al mismo tiempo, también refleja que aprender una tecnología debería comenzar desde la página web oficial para evitar pisar el pozo.
En el proceso de desarrollo propiamente dicho, usando RedisTemplate< K, V> no requiere especificar el tipo de K y V, y el bean por defecto puede cumplir con los requisitos.

Por último, quiero verificar un pequeño problema y modificar el código de nuevo de la siguiente manera:


El código anterior especifica que K y V son ambos tipos de String al inyectar RedisTemplate, y compara si redisTemplate y stringRedisTemplate son el mismo objeto en el método compar(). Ejecuta la clase de prueba unitaria y los resultados de la prueba son los siguientes:

2018-08-10 18:30:57.075 - Inicié Demo1ApplicationTests en 15,58 segundos (JVM funcionando para 16,974)
2018-08-10 18:30:57.360 - hashcode:1996087296 para redisTemplate
2018-08-10 18:30:57.360 - stringRedisPlantilla código hash:1996087296
2018-08-10 18:30:57.363 - Resultado de igual(): verdadero
2018-08-10 18:30:57.364 - Resultado comparativo de redisPlantilla y stringRedisPlantilla: verdadero
Los resultados de la prueba muestran que redisTemplate y stringRedisTemplate son el mismo objeto. Espera un momento... ¿Por qué no está mal especificar que K y V son Strings al inyectar RedisTemplate esta vez? Además, los dos objetos resultaron ser el mismo objeto. Echemos un vistazo al código fuente de StringRedisTemplate.

Después de leer el código fuente, ¿lo entiendes? Porque la clase madre de la clase StringRedisTemplate es RedisTemplate< String, String>, y el bean es singleton por defecto, y ambos son naturalmente el mismo objeto.




Anterior:Cast to value type "System.Decimal" falló...
Próximo:Error creando bean con el nombre 'stringRedisTemplate' definido en...
Renuncia:
Todo el software, materiales de programación o artículos publicados por Code Farmer Network son únicamente para fines de aprendizaje e investigación; El contenido anterior no se utilizará con fines comerciales o ilegales; de lo contrario, los usuarios asumirán todas las consecuencias. La información de este sitio proviene de Internet, y las disputas de derechos de autor no tienen nada que ver con este sitio. Debes eliminar completamente el contenido anterior de tu ordenador en un plazo de 24 horas desde la descarga. Si te gusta el programa, por favor apoya el software genuino, compra el registro y obtén mejores servicios genuinos. Si hay alguna infracción, por favor contáctanos por correo electrónico.

Mail To:help@itsvse.com