Recentemente, RedisTemplate è stato utilizzato durante lo sviluppo del progetto, e il test unitario ha richiesto "Field redisTemplate in com.example.demo1.dao.RedisDao richiedeva un bean di tipo 'org.springframework.data.redis.core.RedisTemplate' che non si è potuto trovare un po' di tipo RedisTemplate". Ovviamente, guardando solo questa frase, non possiamo essere sicuri del motivo per cui si presenta questo problema. Ora, pubblica un registro dettagliato degli errori.
2018-08-10 14:53:49.761 - Eccezione rilevata mentre permetteva a TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] di preparare il test Istanza [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) su org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) su org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189) at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131) presso org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) su org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) su org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) su org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) su org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) su org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) su org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) su org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) su org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) su org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) su org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) su org.junit.runners.ParentRunner$2.valuate(ParentRunner.java:268) su org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) presso org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) su org.junit.runners.ParentRunner.run(ParentRunner.java:363) su org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) su org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) su org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) su org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) su org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) su org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) su org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Causato da: org.springframework.beans.factory.UnsatisfedDependencyException: Errore che crea un bean con nome 'redisDao': Dipendenza insoddisfatta espressa attraverso il campo ' redisTemplate'; eccezione annidata è org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualify bean di tipo 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>'Disponibile: Previsto almeno 1 fagiolo che sia candidato autowire. Annotazioni di dipendenza: {@org.springframework.beans.factory.annotation.Autowired(required=true)} su org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) su org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) su org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) su org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) su org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) su org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) su org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) su org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) su org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) su org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) su org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) su org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) su org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) su org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) su org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) su org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) ... 25 fotogrammi comuni omessiti Causato da: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nessun bean qualificante di tipo 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>'Disponibile: Previsto almeno 1 fagiolo che sia candidato autowire. Annotazioni di dipendenza: {@org.springframework.beans.factory.annotation.Autowired(required=true)} su org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) su org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) su org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) su org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ... 43 fotogrammi comuni omessi Vedere questo grande registro degli errori è un po' stordente, infatti basta guardare i log chiave degli errori per individuare il problema. Il secondo Causato da nel registro errori stampa il log degli errori chiavi:Nessun fagiolo qualificante di tipo 'org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>。
L'autore esamina il codice scritto e specifica il tipo specifico quando inietta RedisTemplate< K, V>.
Secondo il registro errori, controlla il codice alla riga 1493 della classe DefaultListableBeanFactory, il codice sorgente è il seguente:
Questi due metodi dimostrano che nessun fagiolo può essere abbinato < RedisTemplate String, Object >, quindi come risolvere questo problema? Potresti voler usare RedisTemplate< K, V> senza specificare il tipo specifico, e modificare il codice come segue:
Riavvia il servizio, non viene segnalato alcun errore nel log di avvio e il RedisTemplate inietta con successo il bean. Mi chiedo perché RedisTemplate< String, Object> iniettare fagioli fallisca. Dopo averci pensato a lungo, pensavo che RedisTemplate fosse configurato automaticamente nel framework SpringBoot, e che il valore predefinito nel container fosse l'istanza di RedisTemplate. Pensando a questo, devi consultare i documenti ufficiali del sito web per vedere se ci sono spiegazioni nei documenti ufficiali. Infatti, la sezione 30.1.1 della documentazione ufficiale spiega ancora RedisTemplate.
Indirizzo ufficiale del documento:https://docs.spring.io/spring-bo ... ference/htmlsingle/
Se aggiungi il tuo@Beandi uno qualsiasi tipo autoconfigurato, sostituisce il predefinito (tranne nel caso di RedisTemplate, quando l'esclusione si basa sul nome del bean, redisTemplate, non sul suo tipo). Se aggiungi il tuo bean per il tipo di configurazione automatica, sostituirà quello predefinito. Il mio codice sembra andare bene, aspetta... Questa frase tra parentesi è il punto. Traduci un'onda,Tranne nel caso di RedisTemplate, escludendo in base al nome del fagiolo, non al tipo. L'inglese non è molto buono, e sembra che la traduzione non sia molto fluida.
Ora sembra essere compreso che il RedisTemplate< String, Object > usato @Autowired durante l'iniezione,@Autowired assemblati per tipo di default。 In altre parole, se vuoi ottenere i fagioli > RedisTemplate< String, Object, devi assemblarli secondo i loro nomi. Poi pensa naturalmente di usarlo@Resource, viene assemblato di default secondo il nome。 Modifica nuovamente il codice come segue:
L'annotazione è stata cambiata da @Autowired a @Resource Il progetto è iniziato senza errori ed è stato risolto perfettamente!
Riavvia di nuovo il servizio, il log di avvio non segnala errori e il RedisTemplate< String, Object> inietta con successo il bean. Attraverso questo errore, ho imparato una funzione della classe auto-configuration nel framework SpringBoot. Allo stesso tempo, riflette anche che l'apprendimento di una tecnologia dovrebbe partire dal sito ufficiale per evitare di calpestare la fossa. Nel processo di sviluppo effettivo, utilizzando RedisTemplate< K, V> non è necessario specificare il tipo di K e V, e il fagiolo predefinito può soddisfare i requisiti.
Infine, voglio verificare un piccolo problema e modificare nuovamente il codice come segue:
Il codice sopra specifica che K e V sono entrambi tipi di stringa quando si inietta RedisTemplate, e confronta se redisTemplate e stringRedisTemplate sono lo stesso oggetto nel metodo compar(). Esegui la classe di test unitario e i risultati del test sono i seguenti:
2018-08-10 18:30:57.075 - Avviato Demo1ApplicationTests in 15,58 secondi (JVM in esecuzione per 16,974) 2018-08-10 18:30:57.360 - codice hash:1996087296 per redisTemplate 2018-08-10 18:30:57.360 - stringRedisTemplate codice hash:1996087296 2018-08-10 18:30:57.363 - Risultato di parità(): true 2018-08-10 18:30:57.364 - Risultato comparativo tra redisTemplate e stringRedisTemplate: true I risultati del test mostrano che redisTemplate e stringRedisTemplate sono lo stesso oggetto. Aspetta un attimo... Perché non è sbagliato specificare che K e V sono stringhe quando si inietta RedisTemplate questa volta? Inoltre, i due oggetti si rivelarono essere lo stesso oggetto. Diamo un'occhiata al codice sorgente di StringRedisTemplate.
Dopo aver letto il codice sorgente, capisci che la classe genitore della classe StringRedisTemplate è RedisTemplate< String, String>, e il fagiolo è singleton di default, e i due sono naturalmente lo stesso oggetto.
|