Hiljuti kasutati RedisTemplate'i projekti arenduses ning üksustestimine näitas "Field redisTemplate com.example.demo1.dao.RedisDao nõudis beani tüüpi 'org.springframework.data.redis.core.RedisTemplate', mis ei leitud", mis tähendab "ei leidnud RedisTemplate'i tüüpi uba". Muidugi, vaadates ainult seda lauset, ei saa me kindlalt öelda, miks see probleem tekib. Nüüd postita põhjalik vealogi.
2018-08-10 14:53:49.761 - Tuvastati erand, kui lubati TestExecutionListeneril [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] testi ette valmistada Instants [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) aadressil org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189) aadressil org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131) aadressil org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) aadressil org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) aadressil org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) aadressil org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) aadressil org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) aadressil org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) aadressil org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) aadressil org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) aadressil org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) aadressil org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) aadressil org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) aadressil org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) aadressil org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) aadressil org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) aadressil org.junit.runners.ParentRunner.run(ParentRunner.java:363) aadressil org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) aadressil org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) aadressil org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) aadressil org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) aadressil org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) aadressil org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) aadressil org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Põhjustas: org.springframework.beans.factory.UnsatisfiedDependencyException: Viga ubade loomisel nimega 'redisDao': rahuldamata sõltuvus, mis väljendub välja kaudu ' redisTemplate'; pesastatud erand on org.springframework.beans.factory.NoSuchBeanDefinitionException: Puudub kvalifitseeruv ua tüüpi 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' saadaval: oodatakse vähemalt ühte uba, mis kvalifitseerub automaatse juhtme kandidaadiks. Sõltuvusannotatsioonid: {@org.springframework.beans.factory.annotation.Autowired(required=true)} aadressil org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) aadressil org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) aadressil org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) aadressil org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) aadressil org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) aadressil org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) aadressil org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) aadressil org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) aadressil org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) aadressil org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) aadressil org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) aadressil org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) aadressil org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) aadressil org.springframework.boot.SpringApplication.run(SpringApplication.java:303) aadressil 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 levinud raami on välja jäetud Põhjustas: org.springframework.beans.factory.NoSuchBeanDefinitionException: Puudub kvalifitseeruv ua tüüp 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' saadaval: oodatakse vähemalt ühte uba, mis kvalifitseerub automaatse juhtme kandidaadiks. Sõltuvusannotatsioonid: {@org.springframework.beans.factory.annotation.Autowired(required=true)} aadressil org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) aadressil org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) aadressil org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) aadressil org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ... 43 levinud raami on välja jäetud Selle suure vealogi nägemine on veidi pööritav, tegelikult piisab probleemi leidmiseks vaid võtmevealogide vaatamisest. Teine Põhjustatud by vealogis prindib võtme vealogi:Ei mingit kvalifitseerivat uba tüübiga 'org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>。
Autor vaatab kirjutatud koodi tagasi ja määrab konkreetse tüübi, kui süstib RedisTemplate< K, V>.
Vealogi järgi, kontrolli koodi klassi DefaultListableBeanFactory real 1493, lähtekood on järgmine:
Need kaks meetodit näitavad, et ühtegi uba ei saa sobitada < RedisTemplate stringi, objekti >, nii et kuidas seda probleemi lahendada? Võid soovida kasutada RedisTemplate< K, V> ilma konkreetset tüüpi täpsustamata ja muuta koodi järgmiselt:
Taaskäivita teenus, käivituslogis ei ilmu viga ja RedisTemplate süstib oa edukalt. Mõtlen, miks RedisTemplate< String, Object> ubade süstimine ebaõnnestub. Pärast pikka mõtlemist arvasin, et RedisTemplate on SpringBooti raamistikus automaatselt seadistatud ja vaikimisi konteineri instants on RedisTemplate. Selle peale tuleb vaadata ametlikud veebilehedokumendid, et näha, kas ametlikes veebilehtedes on mingit selgitust. Ja tõepoolest, ametliku dokumentatsiooni paragrahv 30.1.1 selgitab endiselt RedisTemplate'i.
Ametliku dokumendi aadress:https://docs.spring.io/spring-bo ... ference/htmlsingle/
Kui lisad oma@Beankõigi automaatselt konfigureeritavate tüüpide puhul asendab see vaikimisi (välja arvatud RedisTemplate'i puhul, kus välistus põhineb oa nimel redisTemplate, mitte selle tüübil). Kui lisad oma oa automaatse seadistamise tüübi jaoks, asendab see vaikimisi. Minu kood tundub korras olevat, oota... See lause sulgudes ongi point. Tõlgi laine,Välja arvatud RedisTemplate'i puhul, kus välistatakse oa nime, mitte tüübi järgi. Inglise keel pole väga hea ja tundub, et tõlge pole väga sujuv.
Nüüd tundub, et RedisTemplate< string, Object > @Autowired kasutati süstimisel,@Autowired vaikimisi tüübi järgi kokku pandud。 Teisisõnu, kui tahad saada ube RedisTemplate< stringi, objekti >, pead need nimede järgi kokku panema. Siis mõtle loomulikult selle kasutamisele@Resource on see vaikimisi kokku pandud vastavalt nimele。 Muuda koodi uuesti järgmiselt:
Annotatsioon on muudetud @Autowired-st @Resource Projekt algas veatult ja sai täiuslikult lahendatud!
Taaskäivita teenus uuesti, käivituslogi ei teata veast ning RedisTemplate< string, Object> süstivad oa edukalt. Selle vea kaudu õppisin SpringBooti raamistikus automaatse konfiguratsiooni klassi funktsiooni. Samas peegeldab see ka seda, et tehnoloogia õppimine peaks algama ametlikult veebilehelt, et vältida auku astumist. Tegelikus arendusprotsessis, kasutades RedisTemplate< K-d, ei nõua V> K ja V tüüpide määramist ning vaikimisi ua suudab nõuded täita.
Lõpuks tahan kontrollida väikest probleemi ja muuta koodi uuesti järgmiselt:
Ülaltoodud kood täpsustab, et K ja V on mõlemad stringitüübid, kui süstitakse RedisTemplate'i, ning võrdleb, kas redisTemplate ja stringRedisTemplate on compare() meetodis sama objekt. Käivita ühiktesti klassi ja testitulemused on järgmised:
2018-08-10 18:30:57.075 - Alustas Demo1ApplicationTeste 15,58 sekundiga (JVM jooksis 16,974 sekundiga) 2018-08-10 18:30:57.360 - hashcode:1996087296 redisTemplate jaoks 2018-08-10 18:30:57.360 - stringRedisTemplate hashcode:1996087296 2018-08-10 18:30:57.363 - Tulemus võrdne(): tõene 2018-08-10 18:30:57.364 - redisTemplate'i ja stringRedisTemplate'i võrdlustulemus: true Testitulemused näitavad, et redisTemplate ja stringRedisTemplate on sama objekt. Oota üks minut... Miks pole vale seekord RedisTemplate'i süstimisel täpsustada, et K ja V on stringid? Veelgi enam, need kaks objekti osutusid samaks objektiks. Vaatame StringRedisTemplate'i lähtekoodi.
Pärast lähtekoodi lugemist, kas sa saad aru, sest StringRedisTemplate klassi vanemklass on RedisTemplate< String, String> ja bean on vaikimisi singleton, ning need kaks on loomulikult sama objekt.
|