Acest articol este un articol oglindă al traducerii automate, vă rugăm să faceți clic aici pentru a sări la articolul original.

Vedere: 15336|Răspunde: 0

[Sursă] Excepția este rezolvată prin injectarea instanței RedisTemplate în SpringBoot

[Copiază linkul]
Postat pe 11.03.2019 13:25:56 | | | |
Recent, RedisTemplate a fost folosit în timpul dezvoltării proiectului, iar testarea unitară a solicitat "Field redisTemplate în com.example.demo1.dao.RedisDao a necesitat un bean de tip 'org.springframework.data.redis.core.RedisTemplate' care nu a putut fi găsit", ceea ce se traduce prin "nu am putut găsi o boabă de tip RedisTemplate". Desigur, uitându-ne doar la această propoziție, nu putem fi siguri de ce apare această problemă. Acum, postează un jurnal detaliat de erori.

2018-08-10 14:53:49.761 - S-a prins o excepție în timp ce TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] a pregătit testul Instanță [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    la org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    la org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
    la org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
    la org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    la org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    la org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    la org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    la org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    la org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    la org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    la org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    la org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    la org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    la org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    la org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    la org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    la org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    la org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    la org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    la org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    la org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    la org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    la org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    la org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    la org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Cauzat de: org.springframework.beans.factory.UnsatisfedDependencyException: Eroare creând bean cu numele 'redisDao': Dependență nesatisfăcută exprimată prin câmpul ' redisTemplate'; Excepția imbricată este org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualify bean de tip 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>Disponibil: Se așteaptă cel puțin 1 boabă care să se califice ca candidat pentru autowire. Adnotări de dependențe: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    la org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    la org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    la org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    la org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    la org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    la org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    la org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    la org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    la org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    la org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    la org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    la org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    la org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    la org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    la org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    la org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    la org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
    la org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    la org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 25 de cadre comune omise
Cauzat de: org.springframework.beans.factory.NoSuchBeanDefinition Exception: Nicio boabă calificantă de tip 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>Disponibil: Se așteaptă cel puțin 1 boabă care să se califice ca candidat pentru autowire. Adnotări de dependențe: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    la org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
    la org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    la org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    la org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 43 de cadre comune omise
Să vezi acest jurnal mare de erori este puțin amețitor, de fapt, trebuie doar să ne uităm la jurnalele cheie de erori pentru a localiza problema. Al doilea Cauzat de în jurnalul de erori afișează jurnalul de eroare cheie:Nu există un bean calificant de tip 'org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>。

Autorul analizează codul scris și specifică tipul specific atunci când injectează RedisTemplate< K, V>.


Conform jurnalului de erori, verificați codul de pe linia 1493 a clasei DefaultListableBeanFactory, codul sursă este următorul:

Aceste două metode arată că nicio boabă nu poate fi potrivită < RedisTemplate String, Object >, deci cum să rezolvi această problemă? Poate doriți să folosiți RedisTemplate< K, V> fără a specifica tipul specific și să modificați codul astfel:

Repornește serviciul, nu se raportează nicio eroare în jurnalul de pornire, iar RedisTemplate injectează cu succes boabea. Mă întreb de ce eșuează injectarea boabelor RedisTemplate< String, Object> După ce m-am gândit mult la asta, am crezut că RedisTemplate este configurat automat în cadrul SpringBoot, iar implicit în container este instanța RedisTemplate. Gândindu-te la asta, trebuie să răsfoiești documentele oficiale de pe site-ul oficial pentru a vedea dacă există vreo explicație în documentele oficiale. Desigur, secțiunea 30.1.1 din documentația oficială încă explică RedisTemplate.

Adresa documentului oficial:https://docs.spring.io/spring-bo ... ference/htmlsingle/




Dacă adaugi propriul tău@Beandin oricare dintre tipurile autoconfigurate, înlocuiește implicitul (cu excepția cazului RedisTemplate, când excluderea se bazează pe numele bean, redisTemplate, nu pe tipul său).
Dacă adaugi propriul tău bean pentru tipul de configurare automată, acesta îl va înlocui pe cel implicit. Codul meu pare să fie în regulă, stai... Această propoziție între paranteze este esențială. Traduce un val,Cu excepția cazului RedisTemplate, când excluzi pe baza numelui boabei, nu a tipului său. Engleza nu este foarte bună și se pare că traducerea nu este foarte fluidă.

Acum pare să se înțeleagă că RedisTemplate< String, Object > folosit @Autowired la injectare,@Autowired asamblat implicit după tip。 Cu alte cuvinte, dacă vrei să obții boabele > RedisTemplate< String, Object, trebuie să le asamblezi după numele lor. Apoi, în mod natural, gândește-te să-l folosești@Resource, este asamblată implicit după denumire。 Modificați din nou codul astfel:


Adnotarea a fost schimbată de la @Autowired la @Resource Proiectul a început fără eroare și a fost rezolvat perfect!

Repornește serviciul din nou, jurnalul de pornire nu raportează o eroare, iar RedisTemplate< String, Object> injectează cu succes bean-ul. Prin această eroare, am învățat o funcție a clasei de auto-configurare din cadrul SpringBoot. În același timp, reflectă și faptul că învățarea unei tehnologii ar trebui să înceapă de pe site-ul oficial pentru a evita să calci pe groapă.
În procesul propriu-zis de dezvoltare, folosind RedisTemplate< K, V> nu necesită specificarea tipului de K și V, iar bean-ul implicit poate îndeplini cerințele.

În final, vreau să verific o mică problemă și să modific din nou codul astfel:


Codul de mai sus specifică faptul că K și V sunt ambele tipuri de String atunci când injectezi RedisTemplate și compară dacă redisTemplate și stringRedisTemplate sunt același obiect în metoda compar(). Rulează clasa de test unitar, iar rezultatele testului sunt următoarele:

2018-08-10 18:30:57.075 - Am început Demo1ApplicationTests în 15,58 secunde (JVM rulând pentru 16,974)
2018-08-10 18:30:57.360 - hashcode:1996087296 pentru redisTemplate
2018-08-10 18:30:57.360 - stringRedisTemplate hashcode:1996087296
2018-08-10 18:30:57.363 - Rezultat egal(): true
2018-08-10 18:30:57.364 - Rezultatul comparației dintre redisTemplate și stringRedisTemplate: true
Rezultatele testelor arată că redisTemplate și stringRedisTemplate sunt același obiect. Aşteaptă puţin... De ce nu este greșit să specifici că K și V sunt Stringuri atunci când injectezi RedisTemplate de data aceasta? Mai mult, cele două obiecte s-au dovedit a fi același obiect. Să aruncăm o privire asupra codului sursă al StringRedisTemplate.

După ce ai citit codul sursă, înțelegi, pentru că clasa părinte a clasei StringRedisTemplate este RedisTemplate< String, String>, iar boabe-ul este singleton în mod implicit, iar cele două sunt în mod natural același obiect.




Precedent:Cast la valoarea tipului "System.Decimal" a eșuat...
Următor:Eroare de creare a unui bean cu numele 'stringRedisTemplate' definit în...
Disclaimer:
Tot software-ul, materialele de programare sau articolele publicate de Code Farmer Network sunt destinate exclusiv scopurilor de învățare și cercetare; Conținutul de mai sus nu va fi folosit în scopuri comerciale sau ilegale, altfel utilizatorii vor suporta toate consecințele. Informațiile de pe acest site provin de pe Internet, iar disputele privind drepturile de autor nu au legătură cu acest site. Trebuie să ștergi complet conținutul de mai sus de pe calculatorul tău în termen de 24 de ore de la descărcare. Dacă îți place programul, te rugăm să susții software-ul autentic, să cumperi înregistrarea și să primești servicii autentice mai bune. Dacă există vreo încălcare, vă rugăm să ne contactați prin e-mail.

Mail To:help@itsvse.com