對Spring源碼的學習:一

目錄

BeanFactory開發流程

ApplicationContext

BeanFactory與ApplicationContext對比

基于XML方式的Bean的配置

自動裝配


BeanFactory開發流程

這里的第三方指的是Spring提供的BeanFactory,Spring啟動時會初始化BeanFactory,然后讀取配置清單(xml文件)獲取需要被加載的bean。實現上面流程圖的具體代碼如下

創建beans.xml文件

public class Test {public static void main(String[] args) {//定義出一個bean工廠DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();//讀取xml文件的讀取器XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);//讀取配置文件reader.loadBeanDefinitions("beans.xml");UserService userService = (UserService) beanFactory.getBean("userService");System.out.println(userService);}
}

因為我們在開發中要遵循三層架構,業務層需要定義數據層,那么接下來我們再在xml文件中指定要一個數據層bean。代碼如下

public class UserServiceImpl implements UserService {//該方法由beanFactory來調用,set注入public void setUserDao(UserDao userDao){System.out.println("由bean工廠調用該set方法");}
}

需要注意的是,需要property標簽中的屬性的name應該是setXxx()方法中的Xxx第一個子母小寫之后的字符,ref標簽指的是bean定義的id。接下來我們查看Test類的運行結果

public class Test {public static void main(String[] args) {//定義出一個bean工廠DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();//讀取xml文件的讀取器XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);//讀取配置文件reader.loadBeanDefinitions("beans.xml");UserService userService = (UserService) beanFactory.getBean("userService");}
}

執行結果截圖?

BeanFactory是Spring中最重要的核心類,下文中的ApplicationContext雖然叫做Spring容器,但實際上在該類中最后調用的還是BeanFactory。

ApplicationContext

ApplicationContext稱為Spring容器,內部封裝了BeanFactory,比BeanFactory功能更豐富,使用ApplicationContext時,xml文件配置我們習慣叫做applicationContext.xml。接下來是一個示例代碼

public class ApplicationContextTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");Object userService = context.getBean("userService");}
}

BeanFactory與ApplicationContext對比

  1. BeanFactory是Spring的早期接口,稱為Spring的Bean工廠,ApplicationContext是后期更高級接口,稱之為Spring 容器
  2. ApplicationContext在BeanFactory基礎上對功能進行了擴展,例如: 監聽功能、國際化功能等。BeanFactory的API更偏向底層,ApplicationContext的API大多數是對這些底層API的封裝;
  3. Bean創建的主要邏輯和功能都被封裝在BeanFactory中ApplicationContext不僅繼承了BeanFactory,而且ApplicationContext內部還維護著BeanFactory的引用,所以,ApplicationContext與BeanFactory既有繼承關系,又有融合關系。
  4. Bean的初始化時機不同,原始BeanFactory是在首次調用getBean時才進行Bean的創建,而ApplicationContext則是配置文件加載,容器一創建就將Bean都實例化并初始化好

基于XML方式的Bean的配置

XmI配置方式

功能描述

<bean id="class="">

Bean的id和全限定名配置

<bean name="">

通過name設置Bean的別名,通過別名也能直接獲取到Bean實例

<bean scope="">

Bean的作用范圍,BeanFactory作為容器時取值singleton和prototype

<bean lazy-init="">

Bean的實例化時機,是否延遲加載。BeanFactory作為容器時無效

<bean init-method="">

Bean實例化后自動執行的初始化方法,method指定方法名

<bean destroy-method="">

Bean實例銷毀前的方法,method指定方法名

<bean autowire="byType">

設置自動注入模式,常用的有按照類型byType,按照名字byName

<bean factory-bean="" factory-method=""/>

指定哪個工廠Bean的哪個方法完成Bean的創建

默認情況下,單純的Spring環境的Bean的作用范圍有兩個:Singleton與Prototype

  • Singleton:單例,默認值,Spring容器創建的時候,就會進行Bean的實例化,并存儲到容器內部的單例池中,每次getBean時都是從單例池中獲取相同的Bean實例。
  • Prototype:原型,Spring容器初始化時不會創建Bean實例,當調用getBean時才會實例化Bean,每次getBean都會創建一個新的Bean實例。

Spring實例化Bean的兩種方式如下:

一:通過構造方法實例化

默認在xml文件中配置的信息都是調用了無參構造器,但是如果我們需要參數時,需要添加constructor-arg標簽,該標簽標識向方法中傳遞參數。

<beans><bean id="userService" class="com.zmt.service.impl.UserServiceImpl"><!-- 默認采用無參構造器,但如果需要參數,則需要進行配置 --><constructor-arg name="參數名稱" value="參數值"></constructor-arg><property name="userDao" ref="userDao"></property></bean><bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean>
</beans>

二:通過調用自定義的工廠方法對Bean進行實例化

靜態工廠方法實例化Bean

public class MyBeanFactory {public static UserDao getUserDao(){//在實例化Bean之前,我們可以進行一些業務邏輯操作return new UserDaoImpl();}
}
  <beans><!--指定執行自定義的Bean工廠的指定方法去實例化Bean--><bean id="userDao1" class="com.zmt.factory.MyBeanFactory" factory-method="getUserDao"></bean><bean id="userService" class="com.zmt.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean><bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean></beans>

可以看到執行結果,一個是通過無參構造器創建出來的Bean一個是通過自定義的靜態工廠創建的。

實例工廠方法實例化Bean

與靜態工廠方法實例化Bean區別在于,我們需要將工廠類也加載為Bean對象,然后通過該Bean對象去實例化

public class MyBeanFactory1 {public UserDao getUserDao(){//在實例化Bean之前,我們可以進行一些業務邏輯操作return new UserDaoImpl();}
}
<beans><!--加載工廠Bean--><bean id="myBeanFactory1" class="com.zmt.factory.MyBeanFactory1"></bean><!--通過工廠Bean去獲取需要的對象--><bean id="userDao2" factory-bean="myBeanFactory1" factory-method="getUserDao"></bean><!--指定執行自定義的Bean工廠的指定方法去實例化Bean--><bean id="userDao1" class="com.zmt.factory.MyBeanFactory" factory-method="getUserDao"></bean><bean id="userService" class="com.zmt.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean><bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean>
</beans>

實現FactoryBean規范延遲實例化Bean

//需要指定FactoryBean的泛型
public class MyBeanFactory2 implements FactoryBean<UserDao> {//該方法在執行getBean的時候去執行@Overridepublic UserDao getObject() throws Exception {return new UserDaoImpl();}//獲取該Bean工廠產生的Bean類型@Overridepublic Class<?> getObjectType() {return UserDao.class;}
}
  <beans><!--Bean名稱是userDao3,但加載的是工廠類--><bean id="userDao3" class="com.zmt.factory.MyBeanFactory2"></bean><!--加載工廠Bean--><bean id="myBeanFactory1" class="com.zmt.factory.MyBeanFactory1"></bean><!--通過工廠Bean去獲取需要的對象--><bean id="userDao2" factory-bean="myBeanFactory1" factory-method="getUserDao"></bean><!--指定執行自定義的Bean工廠的指定方法去實例化Bean--><bean id="userDao1" class="com.zmt.factory.MyBeanFactory" factory-method="getUserDao"></bean><bean id="userService" class="com.zmt.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property></bean><bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean></beans>

延遲加載Bean實際上是先加載了工廠Bean類,當需要用到Bean時,會從單例池中獲取FactoryBean后調用該對象中的getObject()方法獲取到真正的的Bean對象,并將該Bean對象緩存在factoryBeanObjectCache中,當使用到該Bean對象時從該Map中獲取。

自動裝配

我們通過編寫property標簽進行的注入叫做手動注入,而自動裝配是不需要編寫property標簽的,而是在bean標簽中使用autowire屬性來實現自動注入,aotuwire的值有兩個:byName、byType

  • byName:通過屬性名自動裝配,去匹配setXxx與id="xxx"是否一致
  • byType:通過Bean的類型從容器中匹配,匹配出多個相同Bean類型時,報錯

UserServiceImpl存在一個setUserDao方法,因此我們可以這么編寫,同樣可以將屬性注入到UserServiceImpl中

<beans><bean id="userService" class="com.zmt.service.impl.UserServiceImpl" autowire="byName"></bean><bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean>
</beans>

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

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

相關文章

外匯天眼:什么時段做外匯交易最好,有所謂的“最佳時間點”嗎?

在外匯交易的時候&#xff0c;很多手動交易的投資者不知道到底什么時間段操作交易最適合自己。 我們在進行選擇最佳交易時間的時候&#xff0c;一定要明白各時間段的全球各個市場的交易狀況&#xff0c;這樣你才能分配好自己的時間。 當然在通過技術分析與基本分析選擇好幣種后…

PostgreSQL 索引介紹和使用事項

索引內容 關鍵點 索引是一種數據結構&#xff0c;用于加快數據庫查詢的速度。它類似于書籍的目錄&#xff0c;可以快速定位到特定的數據頁。 PG數據庫支持多種類型的索引&#xff0c;包括B樹索引、哈希索引、GiST索引、SP-GiST索引和GIN索引等。 B樹索引是PG數據庫中最常用的…

Google剛發布AlphaCode 2,讓我們碼農多了個小伙伴一起干活

除了其Gemini生成式人工智能模型之外&#xff0c;谷歌今天早上發布了AlphaCode 2&#xff0c;這是谷歌DeepMind實驗室大約一年前推出的代碼生成AlphaCode的改進版本。 事實上&#xff0c;AlphaCode 2實際上由Gemini提供支持&#xff0c;或者至少是由Gemini的某個變體&#xff…

Linux學習教程(第十五章 Linux系統日志管理)

第十五章 Linux系統日志管理 系統日志詳細地記錄了在什么時間&#xff0c;哪臺服務器、哪個程序或服務出現了什么情況。不管是哪種操作系統&#xff0c;都詳細地記錄了重要程序和服務的日志&#xff0c;只是我們很少養成查看日志的習慣。 日志是系統信息最詳細、最準確的記錄者…

煤炭物流行業分析:中國各個分布地區生產占比調研

煤炭物流是指從煤炭生產所需物料進入企業開始&#xff0c;直至把商品煤運達客戶為止的全過程的物流活動。廣義的講&#xff0c;煤炭物流包括煤炭企業原材料的采購、原煤開采、洗選加工、儲存、運輸、銷售以及礦巖等廢棄物的綜合利用諸多環節。狹義的講&#xff0c;煤炭物流是指…

基于個微機器人的開發

簡要描述&#xff1a; 下載消息中的動圖 請求URL&#xff1a; http://域名/getMsgEmoji 請求方式&#xff1a; POST 請求頭Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 參數&#xff1a; 參數名必選類型說明…

spring boot 事件機制

目錄 概述實踐監聽spring boot ready事件代碼 源碼初始化流程調用流程 結束 概述 spring boot 版本為 2.7.17 。 整體看一下spring及spring boot 相關事件。 根據下文所給的源碼關鍵處&#xff0c;打上斷點&#xff0c;可以進行快速調試。降低源碼閱讀難度。 實踐 spring…

TCP聊天

一、項目創建 二、代碼 Client類 package tcp;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner;public class Client {public static void m…

電子學會C/C++編程等級考試2022年06月(四級)真題解析

C/C++等級考試(1~8級)全部真題?點這里 第1題:公共子序列 我們稱序列Z = < z1, z2, ..., zk >是序列X = < x1, x2, ..., xm >的子序列當且僅當存在 嚴格上升 的序列< i1, i2, ..., ik >,使得對j = 1, 2, ... ,k, 有xij = zj。比如Z = < a, b, f, c &…

QT Windos平臺下打包應用程序

一、windeployqt.exe windeployqt&#xff1a;是 Qt 框架自帶的一個工具&#xff0c;用于將一個 Qt 應用程序在 Windows 操作系統下進行打包。它可以通過掃描應用程序的依賴項獲取所需的 Qt 庫文件、插件和翻譯文件&#xff0c;以及復制應用程序可執行文件和所需的依賴項到指定…

電商價格數據監測接口/品牌商品控價接口/商品數據分析接口/比價搜索API接口,超詳細的接口說明

電商價格數據監測API接口是一種用于監測電商平臺上商品價格的API接口&#xff0c;可以幫助品牌和商家及時獲取商品價格信息&#xff0c;掌握價格動態&#xff0c;進行價格對比和分析&#xff0c;以更好地制定價格策略和進行價格調整。 該接口可以監測多個電商平臺的商品價格信…

VM:Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m

Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize256m; support was removed in 8.0 “JDK 8兼容性指南” 指出&#xff0c;在Java 8中&#xff0c;命令行標志 MaxPermSize 已被刪除。原因是永久代從熱點堆中被移除并被轉移到本地內存。所以為了刪除…

【C++】:搜索二叉樹

朋友們、伙計們&#xff0c;我們又見面了&#xff0c;本期來給大家解讀一下有關多態的知識點&#xff0c;如果看完之后對你有一定的啟發&#xff0c;那么請留下你的三連&#xff0c;祝大家心想事成&#xff01; C 語 言 專 欄&#xff1a;C語言&#xff1a;從入門到精通 數據結…

C語言之動態內存管理(malloc calloc realloc)

C語言之動態內存管理 文章目錄 C語言之動態內存管理1. 為什么要有動態內存管理2. malloc 和 free2.1 malloc2.2 free2.3 例子 3. calloc 和 realloc3.1 calloc3.2 realloc 4. 常見的動態內存錯誤4.1 對NULL指針的解引?操作4.2 對動態開辟空間的越界訪問4.3 對?動態開辟內存使…

女裝品牌網站建設的作用如何

服裝是任何人都需要的必備品&#xff0c;尤其是女裝&#xff0c;由于女性群體愛美追求時尚的心理更高&#xff0c;因此市場中有大量女裝品牌以及大量消費者&#xff0c;其規模非常高&#xff0c;眾多大小品牌林立及消費征集下&#xff0c;商家們經營也并不太容易&#xff0c;企…

Themis: Fast, Strong Order-Fairness in Byzantine Consensus

目錄 筆記后續的研究方向摘要引言秩序井然 Themis: Fast, Strong Order-Fairness in Byzantine Consensus CCS 2023 筆記 后續的研究方向 摘要 我們介紹了Themis&#xff0c;這是一種將交易的公平排序引入&#xff08;許可的&#xff09;拜占庭共識協議的方案&#xff0c;最…

參加百度Apollo技術沙龍—感受自動駕駛的魅力

2023年12月2日下午2點&#xff0c;我有幸參加了百度Apollo技術沙龍&#xff0c;這是一個圍繞Apollo新版本Beta的全面升級展開的深度交流活動。作為一名工程師&#xff0c;我深感榮幸能夠與眾多同行和專家一同探討自動駕駛技術的快速發展 在這次沙龍中&#xff0c;我了解到Apo…

Python:核心知識點整理大全7-筆記

目錄 4.2.5 遺漏了冒號 4.3 創建數值列表 4.3.1 使用函數 range() 4.3.2 使用 range()創建數字列表 結果如下&#xff1a; 4.3.3 對數字列表執行簡單的統計計算 4.3.4 列表解析 4.4 使用列表的一部分 4.4.1 切片 4.4.2 遍歷切片 4.4.3 復制列表 4.2.5 遺漏了冒號 fo…

使用vue-quill-editor(富文本框)禁用粘貼圖片

問題描述&#xff1a;富文本框復制粘貼未走上傳圖片接口&#xff0c;會將復制的圖片解析為base64編碼&#xff0c;為了控制這種情況可選擇禁用粘貼圖片&#xff0c;或者監聽有復制粘貼的圖片走上傳圖片接口 獲取到 quill 對象&#xff0c;可以通過 refs 或者 Quill 對象的 getI…

小程序自動更新功能

小程序自動更新功能 在 .vue 頁面的 script 中添加生命周期&#xff0c;在生命周期內監聽頁面信息 onLoad onLoad(options) {this.getUserInfo()this.intervalId setInterval(() > {this.getUserInfo()}, 3000);},onUnload onUnload: function() {// 在頁面卸載時清除定時…