Tento článek je zrcadlovým článkem o strojovém překladu, klikněte zde pro přechod na původní článek.

Pohled: 15336|Odpověď: 0

[Zdroj] Výjimka se vyřeší injekcí instance RedisTemplate ve SpringBootu

[Kopírovat odkaz]
Zveřejněno 11.03.2019 13:25:56 | | | |
Nedávno byl při vývoji projektu použit RedisTemplate a unit testing vedl k tomu, že "Field redisTemplate in com.example.demo1.dao.RedisDao vyžadoval fazolu typu 'org.springframework.data.redis.core.RedisTemplate', která nebylo možné najít", což znamená "nebylo možné najít zrno typu RedisTemplate". Samozřejmě, když se podíváme jen na tuto větu, nemůžeme si být jisti, proč tento problém vzniká. Teď zveřejň podrobný chybový záznam.

2018-08-10 14:53:49.761 - Zachyceno výjimku při umožnění TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] připravit test instance [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    na 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.prepareTestInstance(ServletTestExecutionListener.java:131)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(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)
    na 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)
    na org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    na org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    na org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    na org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    na 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)
    na org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    na adrese org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Způsobeno: org.springframework.beans.factory.UnsatisfiedDependencyException: Chyba při vytváření fazole s názvem 'redisDao': Nespokojená závislost vyjádřená přes pole ' redisTemplate'; Vnořená výjimka je org.springframework.beans.factory.NoSuchBeanDefinitionException: Žádný kvalifikující bean typu 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' Dostupné: Očekává se alespoň 1 fazole, která splňuje podmínky pro Autowire. Anotace závislostí: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    na org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    na org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    na org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    na org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    na org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    na org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    na org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    na org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    na org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    na org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    na org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    na adrese 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 běžných snímků vynechaných
Způsobeno: org.springframework.beans.factory.NoSuchBeanDefinitionException: Žádný kvalifikující bean typu 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' Dostupné: Očekává se alespoň 1 fazole, která splňuje podmínky pro Autowire. Anotace závislostí: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at 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)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 43 běžných snímků vynecháno
Vidět tento velký chybový záznam je trochu matoucí, ve skutečnosti stačí podívat se na klíčové chybové záznamy, abychom našli problém. Druhý Caused by v error logu vytiskne klíčový error log:No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>。

Autor se při injekci RedisTemplate ohlédne zpět k napsanému kódu a specifikuje konkrétní typ< K, V>.


Podle chybového logu zkontrolujte kód na řádku 1493 třídy DefaultListableBeanFactory, zdrojový kód je následující:

Tyto dvě metody ukazují, že žádný fazole nelze spárovat < RedisTemplate String, Object >, takže jak tento problém vyřešit? Můžete chtít použít RedisTemplate< K, V> bez specifikace konkrétního typu a upravit kód následovně:

Restartuji službu, v záznamu o spuštění se nehlásí žádná chyba a RedisTemplate úspěšně vstřelí zrno. Zajímalo by mě, proč RedisTemplate< String, Object> injektování zrn selhává. Po dlouhém přemýšlení jsem si myslel, že RedisTemplate je automaticky konfigurován ve SpringBoot frameworku a výchozí v kontejneru je instance RedisTemplate. Když o tom přemýšlíte, musíte projít oficiální dokumenty na webu, abyste zjistili, zda v nich není nějaké vysvětlení. A skutečně, sekce 30.1.1 oficiální dokumentace stále vysvětluje RedisTemplate.

Oficiální adresa dokumentu:https://docs.spring.io/spring-bo ... ference/htmlsingle/




Pokud přidáte své vlastní@Beanu všech automaticky konfigurovaných typů nahrazuje výchozí (kromě případu RedisTemplate, kdy je vyloučení založeno na názvu zrna redisTemplate, nikoli na jeho typu).
Pokud přidáte vlastní zrno pro automatickou konfiguraci, nahradí to výchozí. Můj kód vypadá v pořádku, počkej... Tato věta v závorkách je podstatná. Přelož vlnu,Kromě případu RedisTemplate, kdy se vylučuje podle názvu zrna, ne podle druhu. Angličtina není moc dobrá a zdá se, že překlad není příliš plynulý.

Nyní se zdá, že je jasné, že RedisTemplate< řetězec, objekt > použit @Autowired při vkládání,@Autowired sestaven podle typu ve výchozím nastavení。 Jinými slovy, pokud chcete získat zrna > RedisTemplate< String, Object, musíte je sestavit podle jejich názvů. Pak přirozeně přemýšlej o jeho použití@Resource je sestaven automaticky podle názvu。 Kód upravte znovu následovně:


Anotace byla změněna z @Autowired na @Resource Projekt začal bez chyby a byl dokonale vyřešen!

Restartujte službu znovu, spouštěcí log nehlásí chybu a RedisTemplate< String, Object> úspěšně vstříkne zrno. Díky této chybě jsem se naučil funkci třídy automatické konfigurace ve SpringBoot frameworku. Zároveň to také ukazuje, že učení se technologii by mělo začít na oficiálních stránkách, aby se předešlo šlápnutí do jámy.
Při samotném vývoji, při použití RedisTemplate< K, V> nevyžaduje specifikaci typu K a V a výchozí zrno může splnit požadavky.

Nakonec chci ověřit malý problém a kód znovu upravit následovně:


Výše uvedený kód specifikuje, že K a V jsou oba typy řetězců při injekci RedisTemplate, a porovnává, zda jsou redisTemplate a stringRedisTemplate stejný objekt v metodě compare(). Spusť jednotkovou testovací třídu a výsledky testu jsou následující:

2018-08-10 18:30:57.075 - Spustil Demo1ApplicationTests za 15,58 sekundy (JVM běžel 16,974)
2018-08-10 18:30:57.360 - hashcode:1996087296 for redisTemplate
2018-08-10 18:30:57.360 - stringRedisTemplate hashcode:1996087296
2018-08-10 18:30:57.363 - Výsledek equal(): true
2018-08-10 18:30:57.364 - Výsledek srovnání redisTemplate a stringRedisTemplate: true
Výsledky testů ukazují, že redisTemplate a stringRedisTemplate jsou stejný objekt. Počkej minutu... Proč není špatné uvést, že K a V jsou řetězce při injekci RedisTemplate tentokrát? Navíc se ukázalo, že oba objekty jsou tentýž předmět. Podívejme se na zdrojový kód StringRedisTemplate.

Po přečtení zdrojového kódu, chápete, protože nadřazenou třídou třídy StringRedisTemplate je RedisTemplate< String, String> a zrno je ve výchozím nastavení singleton, takže oba jsou přirozeně stejný objekt.




Předchozí:Cast to value typ "System.Decimal" selhal...
Další:Chyba při vytváření fazole s názvem 'stringRedisTemplate' definovaným v...
Zřeknutí se:
Veškerý software, programovací materiály nebo články publikované organizací Code Farmer Network slouží pouze k učení a výzkumu; Výše uvedený obsah nesmí být používán pro komerční ani nelegální účely, jinak nesou všechny důsledky uživatelé. Informace na tomto webu pocházejí z internetu a spory o autorská práva s tímto webem nesouvisí. Musíte výše uvedený obsah ze svého počítače zcela smazat do 24 hodin od stažení. Pokud se vám program líbí, podporujte prosím originální software, kupte si registraci a získejte lepší skutečné služby. Pokud dojde k jakémukoli porušení, kontaktujte nás prosím e-mailem.

Mail To:help@itsvse.com