|
|
Paskelbta 2019-03-11 13:25:56
|
|
|
|

Neseniai RedisTemplate buvo naudojamas projekto kūrimo metu, o vienetų testavimas paskatino "Field redisTemplate com.example.demo1.dao.RedisDao reikalavo pupelės tipo "org.springframework.data.redis.core.RedisTemplate", kad nepavyko rasti", o tai reiškia "nepavyko rasti RedisTemplate tipo pupelės". Žinoma, žvelgdami vien į šį sakinį, negalime būti tikri, kodėl kyla ši problema. Dabar paskelbkite išsamų klaidų žurnalą.
2018-08-10 14:53:49.761 - Užfiksuota išimtis leidžiant TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] paruošti testą egzempliorius [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext adresu org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) adresu org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) adresu org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189) adresu org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131) adresu org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) adresu org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) adresu org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) adresu org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) adresu org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) adresu org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) adresu org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) adresu org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) adresu org.junit.runners.ParentRunner$1.tvarkaraštis(ParentRunner.java:71) adresu org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) adresu org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) adresu org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) adresu org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) adresu org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) adresu org.junit.runners.ParentRunner.run(ParentRunner.java:363) adresu org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) adresu org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) adresu org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) adresu org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) adresu org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) adresu org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) adresu org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Sukėlė: org.springframework.beans.factory.UnsatisfiedDependencyException: klaida kuriant pupeles pavadinimu "redisDao": nepatenkinta priklausomybė, išreikšta per lauką " redisTemplate'; įdėtoji išimtis yra org.springframework.beans.factory.NoSuchBeanDefinitionException: nėra reikalavimus atitinkančių pupelių, kurių tipas yra org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>"Yra: tikimasi bent 1 pupelės, kuri atitinka Autowire kandidato reikalavimus. Priklausomybės komentarai: {@org.springframework.beans.factory.annotation.Autowired(required=true)} adresu org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) adresu org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) adresu org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) adresu org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) adresu org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) adresu org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) adresu org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) adresu org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) adresu org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) adresu org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) adresu org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) adresu org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) adresu org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) adresu org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) adresu org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) adresu org.springframework.boot.SpringApplication.run(SpringApplication.java:303) adresu org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120) adresu org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) adresu org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) ... Praleisti 25 įprasti kadrai Sukėlė: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nėra reikalavimus atitinkančių pupelių, kurių tipas yra org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>"Yra: tikimasi bent 1 pupelės, kuri atitinka Autowire kandidato reikalavimus. Priklausomybės komentarai: {@org.springframework.beans.factory.annotation.Autowired(required=true)} adresu org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) adresu org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) adresu org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) adresu org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ... 43 įprasti kadrai praleisti Pamatę šį didelį klaidų žurnalą šiek tiek svaigsta galva, tiesą sakant, mums tereikia pažvelgti į pagrindinius klaidų žurnalus, kad surastume problemą. Antrasis Sukėlė klaidų žurnale spausdina pagrindinį klaidų žurnalą:Nėra reikalavimus atitinkančių pupelių tipo 'org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>。
Autorius atsigręžia į parašytą kodą ir nurodo konkretų tipą įvedant RedisTemplate< K, V>.
Pagal klaidų žurnalą patikrinkite kodą DefaultListableBeanFactory klasės 1493 eilutėje, šaltinio kodas yra toks:
Šie du metodai rodo, kad nė viena pupelė negali būti suderinta < RedisTemplate String, Object >, taigi kaip išspręsti šią problemą? Galite naudoti RedisTemplate< K, V> nenurodydami konkretaus tipo ir modifikuoti kodą taip:
Iš naujo paleiskite paslaugą, paleisties žurnale nepranešama apie klaidą, o "RedisTemplate" sėkmingai įpurškia pupeles. Įdomu, kodėl nepavyksta RedisTemplate< String, Object> pupelių injekcija. Ilgai apie tai galvojęs, pamaniau, kad "RedisTemplate" automatiškai sukonfigūruojamas "SpringBoot" sistemoje, o numatytasis konteineryje yra "RedisTemplate" egzempliorius. Galvodami apie tai, turite peržiūrėti oficialius svetainės dokumentus, kad pamatytumėte, ar oficialiuose svetainės dokumentuose yra kokių nors paaiškinimų. Žinoma, oficialios dokumentacijos 30.1.1 skyriuje vis dar paaiškinama RedisTemplate.
Oficialus dokumento adresas:https://docs.spring.io/spring-bo ... ference/htmlsingle/
Jei pridėsite savo@Beanbet kurio iš automatiškai sukonfigūruotų tipų, jis pakeičia numatytąjį (išskyrus RedisTemplate atvejį, kai išimtis pagrįsta pupelės pavadinimu, redisTemplate, o ne jo tipu). Jei pridėsite savo pupelę automatinio konfigūravimo tipui, ji pakeis numatytąją. Atrodo, kad mano kodas yra gerai, palaukite... Šis sakinys skliausteliuose yra esmė. Išverskite bangą,Išskyrus "RedisTemplate" atvejį, kai neįtraukiama pagal pupelės pavadinimą, o ne pagal jos tipą. Anglų kalba nėra labai gera, ir atrodo, kad vertimas nėra labai sklandus.
Dabar atrodo, kad suprantama, kad RedisTemplate< eilutė, objektas > naudojamas @Autowired įvedant,@Autowired pagal numatytuosius nustatymus surenkami pagal tipą。 Kitaip tariant, jei norite gauti pupeles > RedisTemplate< String, Object, turite jas surinkti pagal jų pavadinimus. Tada natūraliai pagalvokite apie jo naudojimą@Resource, jis surenkamas pagal numatytuosius nustatymus pagal pavadinimą。 Dar kartą pakeiskite kodą taip:
Anotacija buvo pakeista iš @Autowired į @Resource Projektas prasidėjo be klaidų ir buvo puikiai išspręstas!
Dar kartą paleiskite paslaugą iš naujo, paleisties žurnalas nepraneša apie klaidą, o RedisTemplate< eilutė, objektas> sėkmingai įšvirkščia pupelę. Per šią klaidą sužinojau automatinės konfigūracijos klasės funkciją "SpringBoot" sistemoje. Tuo pačiu metu tai taip pat atspindi, kad technologijos mokymasis turėtų prasidėti nuo oficialios svetainės, kad neužliptumėte ant duobės. Faktiniame kūrimo procese, naudojant RedisTemplate< K, V> nereikia nurodyti K ir V tipo, o numatytoji pupelė gali atitikti reikalavimus.
Galiausiai noriu patikrinti nedidelę problemą ir dar kartą pakeisti kodą taip:
Aukščiau pateiktame kode nurodoma, kad K ir V yra eilučių tipai, kai įleidžiamas RedisTemplate, ir palyginama, ar redisTemplate ir stringRedisTemplate yra tas pats objektas compare() metode. Paleiskite vieneto bandymo klasę ir bandymo rezultatai yra tokie:
2018-08-10 18:30:57.075 - Pradėta Demo1ApplicationTests per 15.58 sekundės (JVM veikia 16.974) 2018-08-10 18:30:57.360 - maišos kodas:1996087296 redisTemplate 2018-08-10 18:30:57.360 - stringRedisTemplate hashcode:1996087296 2018-08-10 18:30:57.363 - Rezultatas equal(): true 2018-08-10 18:30:57.364 - redisTemplate ir stringRedisTemplate palyginimo rezultatas: true Bandymo rezultatai rodo, kad redisTemplate ir stringRedisTemplate yra tas pats objektas. Palauk minutę... Kodėl nėra klaidinga nurodyti, kad K ir V yra eilutės, kai šį kartą įšvirkščiama RedisTemplate? Be to, paaiškėjo, kad abu objektai yra tas pats objektas. Pažvelkime į "StringRedisTemplate" šaltinio kodą.
Perskaitę šaltinio kodą, ar suprantate, nes StringRedisTemplate klasės pirminė klasė yra RedisTemplate< String, String>, o pupelės pagal nutylėjimą yra singletonas, ir abu natūraliai yra tas pats objektas.
|
Ankstesnis:Nepavyko perduoti reikšmės tipui "System.Decimal"...Kitą:Klaida kuriant pupeles, kurių pavadinimas 'stringRedisTemplate', apibrėžtas...
|