spring 屬性注入 @Autowired和@Resource注解使用

眾所周知@Resource 和 @Autowired兩大注解是開發中最常用的兩大注解。兩者有一定的區別:

@Autowired

@Autowired是spring框架提供的注解類,默認按照類型進行裝配。當在容器中找不到對應類型的bean時會拋出NoSuchBeanDefinitionException異常,當存在多個符合條件的bean且沒有指定選擇策略時會拋出BeanNotOfRequiredTypeException異常。

@Autowired也可以按bean的名稱進行裝配,這個時候需要借助@Qualifier注解。

@Autowired
@Qualifier("injectServiceA")
private InjectService injectService;

指定注入的InjectService類型的bean名稱為injectServiceA。

@Autowired還有一個布爾屬性required,默認是true,如果設置成false,找不到對應的依賴不會報錯。就需要代碼邏輯上來判斷是否有當前服務。

@Autowired(required = false)
private InjectService injectService1;
@Resource

@Resource時Java EE提供的注解規范,在 Java EE 容器中同樣可以使用。@Resource 默認情況下(未顯示指定bean名稱)按照名稱(name)進行自動裝配。如果按照名稱找不到會在嘗試按類型進行裝配。這樣看來@Resource相對來說更健壯一些。

@Resource注解可以屬性和set方法上。使用在屬性上就是按屬性名進行尋找bean。

@Resource
private InjectService otherService;

如果要指定名字,可以使用name屬性

@Resource(name="injectServiceA")
private InjectService injectService2;

除了使用name屬性也可以使用@Qualifier注解指定bean名稱。

@Resource
@Qualifier("injectServiceB")
private InjectService injectService3;

也可以指定按類型來裝配

@Resource(type = InjectService.class)
private InjectService injectService4;

因為時按照名稱進行裝配,不會存在多個符合條件的bean,但是會存在類型不匹配問題,拋出BeanNotOfRequiredTypeException異常。

@Primary

不管是@Resource還是@Autowired都存在一個問題,按類型查找時候如果存在多個符合條件的bean就無法完成注入,這個時候可以在被注入的bean上添加@Primary來標識當前bean是多個候選實例中優選選用的bean。找到多個是會優選使用帶有@Primary注解的bean。

@Autowired源碼分析

沒錯@Autowired類型的屬性注入是通過context初始化時候添加的類后置處理器AutowiredAnnotationBeanPostProcessor來完成的。

在AnnotationConfigApplicationContext容器構造方法初始化reader時候會調用AnnotationConfigUtils.registerAnnotationConfigProcessors來注冊processors,這里就會加載注解自動注入的bean后置處理器AutowiredAnnotationBeanPostProcessor。

if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}

AutowiredAnnotationBeanPostProcessor繼承自SmartInstantiationAwareBeanPostProcessor。

那么什么時候調用的postProcessor呢,在bean的初始化過程中,創建完實例后就會進行屬性注入,主要在 AbstractAutowireCapableBeanFactory#populateBean方法來完成。

//...
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {//是否有InstantiationAwareBeanPostProcessor處理器if (pvs == null) {pvs = mbd.getPropertyValues();}//逐個拿出InstantiationAwareBeanPostProcessor,調用postProcessProperties方法。for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}
}

AutowiredAnnotationBeanPostProcessor#postProcessProperties

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);metadata.inject(bean, beanName, pvs);return pvs;
}

這里首先會根據注解讀取所有帶有指定注解的bean屬性和方法。注解包括@Autowired和@Value。如果支持JSR-330,也包含@Inject注解。 這個是在AutowiredAnnotationBeanPostProcessor的構造函數里初始化的。找到帶有對應的注解會封裝成InjectedElement對象集合放到InjectionMetadata的injectedElements屬性里,是一個注解。然后metadata.inject方法會將injectedElements一一進行注入,調用InjectedElement.inject()方法。

AutowiredFieldElement#inject()主要邏輯

Field field = (Field) this.member;
value = resolveFieldValue(field, bean, beanName);
if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);
}

最后會調用beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);方法獲取依賴的值,這里面就有@Autowired注入根據類型的邏輯。將值設置給field完成依賴注入。

@Resource注解源碼分析

@Resource注解的處理過程和@Autowired的過程大致是一致的,只不過其使用的bean處理器是CommonAnnotationBeanPostProcessor。其找到的符合條件的屬性封裝成ResourceElement extends LookupElement。獲取屬性值調用CommonAnnotationBeanPostProcessor.getResourceToInject()方法。

這個就留給自己去看吧。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215434.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215434.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215434.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言中的結構體成員賦值與訪問詳解

C語言中的成員賦值與訪問 在C語言中,我們可以使用不同的方式對結構體變量的成員進行賦值和訪問。本文將詳細介紹這些方式,并通過具體的示例代碼加以說明。 目錄 使用strcpy_s函數賦值字符串直接賦值數字和浮點數結構體變量之間的賦值使用復合文字進行…

周周清(2)----踩坑日記

周一: 1.之前換了一個jdk,然后又改了很多東西,很亂,以至于很多項目都不能直接運行了,所以今天就將ideal刪除并且更新版本到2022.3.3,并且重新將ideal里面的配置環境變量,以及jdk下載安裝配置&a…

數據庫系列之簡要對比下GaussDB和OpenGauss數據庫

GaussDB作為一款企業級的數據庫產品,和開源數據庫OpenGauss之間又是什么樣的關系,剛開始接觸的時候是一頭霧水,因此本文簡要對比下二者的區別,以加深了解。 1、GaussDB和OpenGauss數據庫簡要對比 GaussDB是華為基于PostgreSQL數據…

WPF仿網易云搭建筆記(4):信息流控制之消息訂閱

文章目錄 專欄和Gitee倉庫前言消息訂閱最簡單的案例簡單用例父組件訂閱子組件回調 結果 消息訂閱機制消息token是A還是B?傳遞消息的載體。雙重token重復訂閱問題 結論 專欄和Gitee倉庫 WPF仿網易云 Gitee倉庫 WPF仿網易云 CSDN博客專欄 前言 上一篇文章中,我們簡單…

PHP基礎(1)

PHP是一種服務器端腳本語言,是一種用于開發動態Web應用程序的最流行和廣泛使用的語言之一。它的全稱為“Hypertext Preprocessor”,是一種開源的、可嵌入HTML的腳本語言,可以嵌入到HTML中,也可以直接作為命令行腳本運行。PHP腳本在…

Java小案例-如果您的 Java 應用程序在不做任何事情時正在消耗 CPU,您如何確定它在做什么?

前言 我正在調用供應商的 Java API,在某些服務器上,JVM 在登錄 API 后似乎進入了低優先級輪詢循環(CPU 使用率為 100%)。其他服務器上的同一應用程序不會出現此行為。這發生在 WebSphere 和 Tomcat 上。環境設置起來很棘手&#…

DevOps搭建(四)-GitLab安裝細步驟

在這里我們用docker安裝 1、創建gitlab安裝目錄 mkdir -p /usr/local/docker/gitlab_docker 進入該目錄 cd /usr/local/docker/gitlab_docker 2、下載gitlab鏡像 docker pull gitlab/gitlab-ce:latest 3、創建docker-compose.yml vi docker-compose.yml 輸入以下內容保…

理解 HTTP POST 請求:表單與 JSON 數據格式深入解析20231208

引言 在日常的 Web 開發中,理解 HTTP POST 請求的不同數據格式是至關重要的。這不僅有助于構建健壯的后端服務,還能確保與其他服務的有效溝通。本文將深入探討 multipart/form-data 和 application/json,這兩種常見的 POST 請求格式。 POST…

2023 年安徽省職業院校技能大賽高職組“軟件測試”賽項樣題

2023 年安徽省職業院校技能大賽 高職組“軟件測試”賽項樣題 目錄 任務一:功能測試(45 分) 1、測試計劃(5 分) 2、測試用例(15 分) 3、Bug 清單(20 分) 4、測試報告&…

Python 學習筆記之 networkx 使用

介紹 networkx networkx 支持創建簡單無向圖、有向圖和多重圖;內置許多標準的圖論算法,節點可為任意數據;支持任意的邊值維度,功能豐富,簡單易用 networkx 中的 Graph Graph 的定義 Graph 是用點和線來刻畫離散事物…

張馳咨詢:數據驅動的質量改進,六西格瑪綠帶在汽車業實踐

尊敬的汽車行業同仁們,您是否曾面臨生產效率低下、成本不斷攀升或顧客滿意度下降的困擾?本期專欄,我們將深入探討如何通過六西格瑪綠帶培訓,在汽車行業中實現過程優化和質量提升。 汽車行業的競爭日趨激烈,致力于提供…

3.cloud-Consul服務注冊與發現

1.官網 https://learn.hashicorp.com/consul/getting-started/install.html 2.訂單服務 2.1 POM <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependenc…

學習Java第66天,路徑問題

相對路徑情況分析 相對路徑情況1:web/index.html中引入web/static/img/logo.png 訪問index.html的url為 : http://localhost:8080/web03_war_exploded/index.html 當前資源為 : index.html 當前資源的所在路徑為 : http://localhost:8080/web03_war_exploded/ 要獲取的目標資…

【華為數據之道學習筆記】3-9元數據治理面臨的挑戰

華為在進行元數據治理以前&#xff0c;遇到的元數據問題主要表現為數據找不到、讀不懂、不可信&#xff0c;數據分析師們往往會陷入數據沼澤中&#xff0c;例如以下常見的場景。 某子公司需要從發貨數據里對設備保修和維保進行區分&#xff0c;用來不對過保設備進行服務場景分析…

Qt 使用百度的離線地圖

使用百度離線地圖&#xff0c;一下載百度離線包&#xff08;offlinemap&#xff09;&#xff1b;二是準備地圖瓦片&#xff08;不同級別的瓦片&#xff09;&#xff1b;三 準備&#xff48;&#xff54;&#xff4d;&#xff4c;主頁面&#xff1b;四&#xff0c;&#xff31;&…

深度學習 Day13——P2彩色圖片分類

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 | 接輔導、項目定制 文章目錄 前言1 我的環境2 代碼實現與執行結果2.1 前期準備2.1.1 引入庫2.1.2 設置GPU&#xff08;如果設備上支持GPU就使用GPU,否則使用C…

在Go中定義方法

引言 函數允許你將邏輯組織到可重復的過程中,每次運行時可以使用不同的參數。在定義函數的過程中,你會經常發現多個函數可能每次都操作同一段數據。Go可以識別這種模式,并允許您定義特殊的函數,稱為方法,其目的是對某些特定類型的實例進行操作,稱為接收器。為類型添加方…

nodejs微信小程序+python+PHP基于spark的酒店管理系統-計算機畢業設計推薦

目 錄 摘 要 I ABSTRACT II 目 錄 II 第1章 緒論 1 1.1背景及意義 1 1.2 國內外研究概況 1 1.3 研究的內容 1 第2章 相關技術 3 2.1 nodejs簡介 4 2.2 express框架介紹 6 2.4 MySQL數據庫 4 第3章 系統分析 5 3.1 需求分析 5 3.2 系統可行性分析 5 3.2.1技術可行性&#xff1a;…

排序算法——歸并排序

歸并排序&#xff08;Merge Sort&#xff09;是計算機科學中非常重要的排序算法之一。它不僅高效、穩定&#xff0c;而且是許多高級排序技術和算法思想的基礎。在本文中&#xff0c;我們將深入探討歸并排序的原理、實現方法&#xff0c;以及它的優缺點。 1. 歸并排序的原理 歸…

Python大模型TensorFlow/PyTorch/Scikit-learn/Keras/OpenCV/Gensim

Python 作為一種高級編程語言&#xff0c;可以用于開發各種大小的模型。以下是一些常見的 Python 大模型&#xff0c;以及它們的優勢、劣勢和使用場景&#xff1a; TensorFlow&#xff1a; 優勢&#xff1a;TensorFlow 是一個非常流行的深度學習庫&#xff0c;具有高度的可擴…