Эта статья является зеркальной статьёй машинного перевода, пожалуйста, нажмите здесь, чтобы перейти к оригиналу.

Вид: 15336|Ответ: 0

[Источник] Исключение решается инжектором RedisTemplate в SpringBoot

[Скопировать ссылку]
Опубликовано 11.03.2019 13:25:56 | | | |
Недавно при разработке проекта использовался RedisTemplate, и модульное тестирование вызвало «Field redisTemplate in com.example.demo1.dao.RedisDao требовал зерна типа 'org.springframework.data.redis.core.RedisTemplate', который не удалось найти», что переводится как «не удалось найти боб типа RedisTemplate». Конечно, если смотреть только на это предложение, мы не можем понять, почему возникает эта проблема. Теперь опубликуйте подробный журнал ошибок.

2018-08-10 14:53:49.761 - Обнаружено исключение при разрешении TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] подготовить тест экземпляр [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext
    на org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    на org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    на org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary (ServletTestExecutionListener.java:189)
    на сайте org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
    на сайте org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    на org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    на org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    на сайте org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    на org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    на org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    на org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    на org.junit.runners.ParentRunner$3.run (ParentRunner.java:290)
    на org.junit.runners.ParentRunner$1.расписание(ParentRunner.java:71)
    на org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    на org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    на org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    на сайте org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    на org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    на сайте org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    на org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    на сайте org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    на org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    на сайте org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Причина: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'redisDao': Неудовлетворённая зависимость, выраженная через поле ' redisTemplate'; Вложенное исключение — org.springframework.beans.factory.NoSuchBeanDefinitionException: Нет квалифицирующего bean типа 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' Доступно: ожидается как минимум 1 боб, который подходит как кандидат на Autowire. Аннотации зависимостей: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    на сайте org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    на сайте org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    на org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    на org.springframework.beans.factory.support.abstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    на сайте org.springframework.beans.factory.support.abstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    на сайте org.springframework.beans.factory.support.abstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    на org.springframework.beans.factory.support.abstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    на сайте org.springframework.beans.factory.support.abstractBeanBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    на сайте org.springframework.beans.factory.support.abstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    на org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    на сайте org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    на org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    на org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    на org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    на org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    на сайте org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
    на org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    на org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 25 распространённых кадров пропущены
Причина: org.springframework.beans.factory.NoSuchBeanDefinitionИсключение: Нет квалифицирующего bean типа 'org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>' Доступно: ожидается как минимум 1 боб, который подходит как кандидат на Autowire. Аннотации зависимостей: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    на сайте org.springframework.beans.factory.support.defaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
    на org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    на сайте org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    на сайте org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 43 распространённых кадра пропущены
Видеть такой большой журнал ошибок — это немного головокружительно, на самом деле нам достаточно посмотреть ключевые логи ошибок, чтобы найти проблему. Второй Causeed by в журнале ошибок печатает журнал ключевой ошибки:No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>。

Автор оглядывается на написанный код и указывает конкретный тип при внедрении RedisTemplate< K, V>.


Согласно журналу ошибок, проверьте код на строке 1493 класса DefaultListableBeanFactory, исходный код таков:

Эти два метода показывают, что ни один bean не может быть сопоставлен < строку, объект > RedisTemplate, так как же решить эту проблему? Вы можете использовать RedisTemplate< K, V> без указания конкретного типа и изменить код следующим образом:

Перезапустите сервис, ошибка в журнале запуска не отображается, и RedisTemplate успешно вводит bean. Интересно, почему RedisTemplate< String, Object> инъекция бобов не удаётся. После долгих размышлений я подумал, что RedisTemplate автоматически настроен в фреймворке SpringBoot, а по умолчанию в контейнере является экземпляр RedisTemplate. Учитывая это, вам нужно просмотреть официальные документы сайта, чтобы узнать, есть ли там какие-либо объяснения. И действительно, раздел 30.1.1 официальной документации всё ещё объясняет RedisTemplate.

Официальный адрес документа:https://docs.spring.io/spring-bo ... ference/htmlsingle/




Если вы добавите свои собственные@Beanлюбого из автоматически настроенных типов он заменяет стандартный (за исключением случая RedisTemplate, когда исключение основано на имени bean redisTemplate, а не на типе).
Если добавить свой собственный боб для типа автонастройки, он заменит стандартный. Мой код, похоже, в порядке, подожди... Это предложение в скобках — и есть суть. Переведи волну,За исключением случая RedisTemplate, когда его исключают по названию зерна, а не по типу. Английский язык не очень хорош, и, похоже, перевод не очень плавный.

Теперь, похоже, понятно, что RedisTemplate< строка, объект > использовался @Autowired при инъекции,@Autowired собран по типу по умолчанию。 Другими словами, если вы хотите получить зерна > RedisTemplate< String, Object, вам нужно собирать их согласно названиям. А потом, естественно, думайте о том, чтобы использовать её@Resource она по умолчанию собирается согласно названию。 Снова измените код следующим образом:


Аннотация была изменена с @Autowired на @Resource Проект начался без ошибок и был полностью решен!

При повторном запуске сервиса журнал запуска не сообщает об ошибке, и RedisTemplate< строка, объект> успешно внедряют bean. Из-за этой ошибки я узнал функцию класса автонастройки в фреймворке SpringBoot. В то же время это также показывает, что изучение технологии должно начинаться с официального сайта, чтобы не наступать на яму.
В процессе разработки, используя RedisTemplate< K, V> не требует указания типа K и V, и стандартный боб может соответствовать этим требованиям.

Наконец, я хочу проверить небольшую проблему и снова изменить код следующим образом:


Вышеуказанный код указывает, что K и V являются типами строк при внедрении RedisTemplate, и сравнивает, являются ли redisTemplate и stringRedisTemplate одним и тем же объектом в методе compare(). Запустите класс модульного тестирования, и результаты теста следующие:

2018-08-10 18:30:57.075 - Начало Demo1ApplicationTests за 15,58 секунды (JVM работает 16,974)
2018-08-10 18:30:57.360 - хэшкод:1996087296 для redisTemplate
2018-08-10 18:30:57.360 - stringRedisTemplate хэшкод:1996087296
2018-08-10 18:30:57.363 - Результат равный(): true
2018-08-10 18:30:57.364 - Результаты сравнения redisTemplate и stringRedisTemplate: true
Результаты тестов показывают, что redisTemplate и stringRedisTemplate — это один и тот же объект. Подожди минутку... Почему не ошибочно указывать, что K и V — это Strings при внедрении RedisTemplate в этот раз? Более того, оба объекта оказались одним и тем же объектом. Давайте рассмотрим исходный код StringRedisTemplate.

После прочтения исходного кода вы понимаете, потому что родительский класс класса StringRedisTemplate — RedisTemplate< String, String>, а bean по умолчанию singleton, и эти два объекта естественно одинаковые.




Предыдущий:Заклинание по значению типа «System.Decimal» не удалось...
Следующий:Создание ошибки с названием 'stringRedisTemplate', определённым в...
Отказ:
Всё программное обеспечение, программные материалы или статьи, публикуемые Code Farmer Network, предназначены исключительно для учебных и исследовательских целей; Вышеуказанный контент не должен использоваться в коммерческих или незаконных целях, иначе пользователи несут все последствия. Информация на этом сайте взята из Интернета, и споры по авторским правам не имеют отношения к этому сайту. Вы должны полностью удалить вышеуказанный контент с компьютера в течение 24 часов после загрузки. Если вам нравится программа, пожалуйста, поддержите подлинное программное обеспечение, купите регистрацию и получите лучшие подлинные услуги. Если есть нарушение, пожалуйста, свяжитесь с нами по электронной почте.

Mail To:help@itsvse.com