SpringBoot學習——@Autowired自動注入報:could not be found問題的理解和解決方案
微服務應用程式中,我們會通過Java後臺的方式傳送http請求並呼叫其他註冊在Spring Cloud Eureka server上的微服務,之前我們可能會手動封裝一個Http傳送請求類,然後通過其中的sendGet或者sendPost方法藉由java IO的形式傳送出去。
但是,上述方法過於繁瑣和和臃腫,我們使用org.springframework.web.client.RestTemplate例項,通過幾行程式碼就可以輕鬆傳送我們需要的請求。
然而,在實際的應用程式呼叫時,我通過@Autowired方式將RestTemplate例項注入到類中,
@Autowired
private RestTemplate restTemplate;
在啟動springboot時,控制檯報告啟動失敗:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field restTemplate in com.seco.ad.controller.MobileAdController required a bean of
type 'org.springframework.web.client.RestTemplate' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.web.client.RestTemplate' in your configuration.
可以看到Description:中的描述是RestTemplate未能找到!!!
為什麼?因為Spring容器沒有註冊RestTemplate例項,也就無法通過@Autowired自動注入方式“new”一個RestTemplate例項出來(通過重寫無參構造器的方式,可以發現這種通過@Autowired方式自動注入的例項確實是通過new方法來完成的)。
在之前的@Autowired註解使用中,我們可以輕鬆的將DAO層的依賴物件JdbcTemplate例項順利的自動注入到DAO層的服務中去,而不需要任何類似JavaConfig或者xml配置Bean定義到Spring容器中去,那為什麼RestTemplate就需要?
原來JdbcTemplate 和RestTemplate一樣都是都是spring框架本身提供的元件,但是專案中用到的JdbcTemplate是不需要引數的,可以通過@Autowired自動注入,而不需要初始化,但是RestTemplate需要。另外,在《@Autowired自動注入例項》這篇文章中也可以看到,當需要引數的JdbcTemplate進行自動注入的時候應用程式在啟動時就會發生類似“could not be found”的空指標異常。
因此,回過頭來反思@Autowired自動注入RestTemplate報“could not be found”錯誤的原因,即是此注入例項需要引數!
我在通過網上資料的查詢中找到了正確注入RestTemplate的方法,確實需要將RestTemplate註冊到spring容器中去,另外,還有我們剛剛提到的引數問題,也就是RestTemplate例項的依賴:org.springframework.http.client.ClientHttpRequestFactory。
SpringBoot提倡通過JavaConfig方式註冊我們需要的Bean元素:
package com.seco.ad.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* RestTemplate配置
* 這是一種JavaConfig的容器配置,用於spring容器的bean收集與註冊,並通過引數傳遞的方式實現依賴注入。
* "@Configuration"註解標註的配置類,都是spring容器配置類,springboot通過"@EnableAutoConfiguration"
* 註解將所有標註了"@Configuration"註解的配置類,"一股腦兒"全部注入spring容器中。
*
* @author mht
*
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//ms
factory.setConnectTimeout(15000);//ms
return factory;
}
}
(最近在研讀《SpringBoot揭祕》有關springboot啟動方面的知識中談到了有關@Configuration註解的的作用我寫在了這段code中的JavaDoc裡)
可以看到,在此JavaConfig配置中,我註冊了兩個Bean,而第二個Bean正是我們最終需要的RestTemplate例項的依賴,有了這個配置類,我們回過頭再通過@Autowired方式自動注入我們需要的RestTemplate就不會在springboot啟動時報“無法找到”錯誤了。
令人欣喜的是,將這些思路理清的功臣是《@Autowired自動注入例項》這篇文章。
我試著通過文章中提到的“@Autowired自動注入有引數依賴物件的寫法”編寫類似的程式碼後,發現即便是沒有RestTemplateConfig這個配置類,沒有對spring容器進行bean定義的註冊,依然可以成功的啟動springboot應用程式。寫法如下:
private RestTemplate restTemplate;
private ClientHttpRequestFactory factory;
@Autowired
public void setFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//ms
factory.setConnectTimeout(15000);//ms
this.factory = factory;
}
@Autowired
public void setRestTemplate() {
this.restTemplate = new RestTemplate(this.factory);
}
上述程式碼思路很簡單:設定兩個私有屬性 restTemplate和factory,然後下面先通過設定引數的方式自動完成對factory物件的注入,然後再講factory注入到restTemplate中去,即完成了RestTemplate的注入工作。即便沒有JavaConfig這樣的Bean的註冊配置類,應用程式依然可以啟動成功。
實際上還是圍繞了spring容器的關鍵兩步(引自王富強的《SpringBoot解密》):第一步:收集和註冊;第二步:分析和組裝。
當我們依賴的例項(例如本文中提到的JdbcTemplate和RestTemplate)需要其他的依賴時,當然就不可能僅僅通過@Autowired自動注入到我們需要的類中而不去考慮它們的引數(也就是它們的依賴),因此,不管是通過JavaConfig配置方式還是利用@Autowired完成引數的配置,實際上都是在解決我們最終的依賴與它們自己的依賴的組裝問題。
相關文章
- 專案啟動報錯怎麼辦?看看你Spring自動注入用對了嘛?@Autowired XxxService注入問題解決Spring
- 深入理解springboot的自動注入Spring Boot
- @Autowired 注入 **required a single bean, but 2 were found**UIBean
- GT911驅動遇到的問題和解決方案
- SpringBoot中普通類無法通過@Autowired自動注入Service、dao等bean解決方法Spring BootBean
- Salesforce LWC學習(三十九) lwc下quick action的recordId的問題和解決方案SalesforceUI
- @Resource的作用相當於@Autowired,只不過@Autowired按照byType自動注入
- SpringBoot使用IDEA設定的外部Tomcat啟動,遇到的問題和解決Spring BootIdeaTomcat
- springboot專案解決 No beans of 'UserDao' type found 問題Spring BootBean
- Debian 11 關閉 swap 遇到的問題和解決方案
- Composer 使用過程中遇到的問題和解決方案
- 優思學院|精益生產的各種問題和解決方案
- Intellij IDEA使用@Autowired註解,出現could not autowire錯誤,解決方案IntelliJIdea
- SpringBoot跨域問題解決方案Spring Boot跨域
- 解決Autowired注入失敗為nullNull
- Spring @Autowired 註解自動注入流程是怎麼樣?Spring
- Spring裝配Bean(五)profile註解和解決自動注入的歧義性SpringBean
- svn的操作,報錯,和解決方案 一。
- 有關 Android Studio 重複引入包的問題和解決方案Android
- xxl-job濫用netty導致的問題和解決方案Netty
- 浮動元素引起的問題和解決辦法?
- 浮動元素引起的問題和解決辦法
- PySimpleGUI 引入後VsCode出現問題提示 “could not be resolved” 解決方案GUIVSCode
- Windows作業系統常見故障問題和解決方案Windows作業系統
- 解決bash: mysql: command not found的問題MySql
- 深刻理解JAVA併發中的有序性問題和解決之道Java
- redis分散式鎖的問題和解決Redis分散式
- 介面自動化的關鍵思路和解決方案,本文全講清楚了
- Web 學習之跨域問題及解決方案Web跨域
- 自動化測試:學習Selenium+Python的過程中遇到的坑和解決方法Python
- Spring @Autowired 注入小技巧Spring
- go tool compile 報錯 could not import sync (file not found)GoCompileImport
- 介面自動化報告的問題
- could not autowire. No beans of 'xxxx' 問題解決Bean
- SpringBoot自動配置原理解析Spring Boot
- 粘包問題原因和解決方法
- 談談對分散式事務的一點理解和解決方案分散式
- mysql中出現Unit mysql.service could not be found 的解決方法MySql
- Springboot學習日記(三)自動裝配Spring Boot