|
|
Veröffentlicht am 11.03.2019 13:25:56
|
|
|
|

Kürzlich wurde RedisTemplate während der Projektentwicklung verwendet, und Unit-Tests führten zu "Field redisTemplate in com.example.demo1.dao.RedisDao erforderte eine Bean vom Typ 'org.springframework.data.redis.core.RedisTemplate', die konnte nicht gefunden werden", was übersetzt bedeutet: "konnte keine Bohne vom Typ RedisTemplate finden". Natürlich können wir allein bei diesem Satz nicht sicher sein, warum dieses Problem auftritt. Jetzt poste ein detailliertes Fehlerprotokoll.
2018-08-10 14:53:49.761 – Eine Ausnahme festgestellt, während TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] den Test vorbereitet wurde Instanz [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext bei org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189) at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestTestInstance(ServletTestExecutionListener.java:131) at org.springframework.test.context.TestContextManager.prepareTestTestInstance(TestContextManager.java:230) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) bei org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) unter org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) unter org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) unter org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) unter org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) unter org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) unter org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) bei org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) bei org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) unter org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) unter org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) unter org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) unter org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Verursacht von: org.springframework.beans.factory.UnsatisfiedDependencyException: Fehler zum Erstellen von Bohne mit dem Namen 'redisDao': Unzufriedene Abhängigkeit wird durch das Feld ' ausgedrückt redisTemplate'; verschachtelte Ausnahme ist org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' Verfügbar: Erwartet mindestens 1 Bohne, was als Autowire-Kandidat gilt. Abhängigkeitsannotationen: {@org.springframework.beans.factory.annotation.Autowired(required=true)} bei org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) bei org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) bei org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) bei org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) bei org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) bei org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) unter org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) bei org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) bei 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 häufige Rahmen ausgelassen Verursacht von: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' Verfügbar: Erwartet mindestens 1 Bohne, was als Autowire-Kandidat gilt. Abhängigkeitsannotationen: {@org.springframework.beans.factory.annotation.Autowired(required=true)} bei org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) bei org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ... 43 gängige Rahmen weggelassen Dieses große Fehlerprotokoll ist etwas schwindelerregend, tatsächlich müssen wir nur die wichtigsten Fehlerprotokolle durchsehen, um das Problem zu finden. Das zweite Verursacht durch im Fehlerprotokoll druckt das Schlüssel-Fehlerprotokoll:No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>。
Der Autor schaut sich den geschriebenen Code noch einmal an und spezifiziert den spezifischen Typ, wenn er RedisTemplate injiziert< K, V>.
Laut dem Fehlerprotokoll, prüfen Sie den Code auf Zeile 1493 der Klasse DefaultListableBeanFactory, der Quellcode ist wie folgt:
Diese beiden Methoden zeigen, dass keine Bohne < RedisTemplate String, Object > abgeglichen werden kann – wie löst man dieses Problem? Sie können RedisTemplate< K, V> verwenden, ohne den spezifischen Typ anzugeben, und den Code wie folgt ändern:
Neustart des Dienstes, es wird kein Fehler im Startprotokoll gemeldet, und die RedisTemplate injiziert die Bohne erfolgreich. Ich frage mich, warum RedisTemplate< String, Object> Bohneninjektion fehlschlägt. Nachdem ich lange darüber nachgedacht habe, dachte ich, dass RedisTemplate im SpringBoot-Framework automatisch konfiguriert ist und der Standard im Container die Instanz von RedisTemplate ist. In diesem Zusammenhang sollten Sie die offiziellen Website-Dokumente durchsehen, um zu sehen, ob es eine Erklärung in den offiziellen Website-Dokumenten gibt. Tatsächlich erklärt Abschnitt 30.1.1 der offiziellen Dokumentation immer noch RedisTemplate.
Offizielle Dokumentadresse:https://docs.spring.io/spring-bo ... ference/htmlsingle/
Wenn du deine eigenen hinzufügst@Beanvon allen automatisch konfigurierten Typen ersetzt er den Standard-Typ (außer im Fall von RedisTemplate, wenn der Ausschluss auf dem Bean-Namen redisTemplate basiert, nicht auf dessen Typ). Wenn du deine eigene Bohne für den Auto-Konfigurationstyp hinzufügst, ersetzt sie die Standardvariante. Mein Code scheint in Ordnung zu sein, warte... Dieser Satz in Klammern ist der Punkt. Übersetze eine Welle,Außer im Fall von RedisTemplate, wenn man aufgrund des Namens der Bohne ausschließt, nicht wegen des Typs. Das Englische ist nicht sehr gut, und es scheint, dass die Übersetzung nicht sehr flüssig ist.
Nun scheint es verstanden zu sein, dass das RedisTemplate< String-Objekt beim Injizieren @Autowired verwendet >,@Autowired standardmäßig nach Typ zusammengesetzt。 Mit anderen Worten: Wenn du die Bohnen > RedisTemplate< String, Object bekommen willst, musst du sie nach ihren Namen zusammenstellen. Dann denke natürlich darüber nach, es zu benutzen@Resource wird es standardmäßig gemäß dem Namen zusammengesetzt。 Ändern Sie den Code erneut wie folgt:
Die Annotation wurde von @Autowired auf @Resource geändert. Das Projekt startete fehlerfrei und wurde perfekt gelöst!
Neustart des Dienstes erneut, das Startprotokoll meldet keinen Fehler und die RedisTemplate< String, Object> injizieren die Bohne erfolgreich. Durch diesen Fehler habe ich eine Funktion der Auto-Konfigurationsklasse im SpringBoot-Framework gelernt. Gleichzeitig spiegelt es auch wider, dass das Erlernen einer Technologie auf der offiziellen Website beginnen sollte, um nicht in die Grube zu treten. Im eigentlichen Entwicklungsprozess erfordert die Verwendung von RedisTemplate< K, V> keine Angabe des Typs von K und V, und die Standardbohne kann die Anforderungen erfüllen.
Abschließend möchte ich ein kleines Problem überprüfen und den Code erneut wie folgt ändern:
Der obige Code spezifiziert, dass K und V beide String-Typen sind, wenn RedisTemplate injiziert wird, und vergleicht, ob redisTemplate und stringRedisTemplate dasselbe Objekt in der Methode compare() sind. Führen Sie die Unit Test-Klasse aus, und die Testergebnisse sind wie folgt:
2018-08-10 18:30:57.075 - Demo1ApplicationTests in 15,58 Sekunden gestartet (JVM läuft mit 16,974 Sekunden) 2018-08-10 18:30:57.360 - hashcode:1996087296 für redisTemplate 2018-08-10 18:30:57.360 - stringRedisTemplate hashcode:1996087296 2018-08-10 18:30:57.363 - Ergebnis gleich(): wahr 2018-08-10 18:30:57.364 - Vergleichsergebnis von redisTemplate und stringRedisTemplate: true Die Testergebnisse zeigen, dass redisTemplate und stringRedisTemplate dasselbe Objekt sind. Augenblick mal... Warum ist es nicht falsch, beim Injekten von RedisTemplate diesmal anzugeben, dass K und V Strings sind? Außerdem stellten sich die beiden Objekte als dasselbe Objekt heraus. Schauen wir uns den Quellcode von StringRedisTemplate an.
Nachdem du den Quellcode gelesen hast, verstehst du das, denn die Elternklasse der StringRedisTemplate-Klasse ist RedisTemplate< String, String> und der Bean ist standardmäßig Singleton, und die beiden sind natürlich dasselbe Objekt?
|
Vorhergehend:Auf Wert-Typ "System. Dezimal" gewirkt, fehlgeschlagen...Nächster:Fehler beim Erstellen von Bohne mit dem Namen 'stringRedisTemplate' definiert in...
|