【Spring源碼】小白速通解析Spring源碼,從0到1,持續更新!

Spring源碼

參考資料

https://www.bilibili.com/video/BV1Tz4y1a7FM

https://www.bilibili.com/video/BV1iz4y1b75q

image-20230727230632443

bean工廠

DefaultListableBeanFactory(最原始)

bean的生命周期

創建(實例化)–>依賴注入–>-初始化–>銷毀

bean–>推斷構造方法(默認是無參構造,或指定的構造方法)–>實例化成普通對象(相當于new bean)

–>進行依賴注入(bean里的屬性)–>執行afterPropertiesSet()(InitializingBean的一個回調方法,同@PostConstruct)

–>初始化后是否需要AOP–>AOP–>代理對象(target=普通對象)–>把對象放入Map<beanname,bean對象>單例池

image-20230817225424846

//真正創建Bean的方法protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.//封裝被創建的Bean對象BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();//獲取實例化對象的類型Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.//調用PostProcessor后置處理器synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.//向容器中緩存單例模式的Bean對象,以防循環引用boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}//這里是一個匿名內部類,為了防止循環引用,盡早持有對象的引用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.//Bean對象的初始化,依賴注入在此觸發//這個exposedObject在初始化完成之后返回作為依賴注入完成后的BeanObject exposedObject = bean;try {//將Bean實例對象封裝,并且Bean定義中配置的屬性值賦值給實例對象populateBean(beanName, mbd, instanceWrapper);//初始化Bean對象exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {//獲取指定名稱的已注冊的單例模式Bean對象Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {//根據名稱獲取的已注冊的Bean和正在實例化的Bean是同一個if (exposedObject == bean) {//當前實例化的Bean初始化完成exposedObject = earlySingletonReference;}//當前Bean依賴其他Bean,并且當發生循環引用時不允許新創建實例對象else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);//獲取當前Bean所依賴的其他Beanfor (String dependentBean : dependentBeans) {//對依賴Bean進行類型檢查if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.//注冊完成依賴注入的Beantry {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}
//初始容器創建的Bean實例對象,為其添加BeanPostProcessor后置處理器protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {//JDK的安全機制驗證權限if (System.getSecurityManager() != null) {//實現PrivilegedAction接口的匿名內部類AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {//為Bean實例對象包裝相關屬性,如名稱,類加載器,所屬容器等信息invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;//對BeanPostProcessor后置處理器的postProcessBeforeInitialization//回調方法的調用,為Bean實例初始化前做一些處理if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}//調用Bean實例對象初始化的方法,這個初始化方法是在Spring Bean定義配置//文件中通過init-method屬性指定的try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}//對BeanPostProcessor后置處理器的postProcessAfterInitialization//回調方法的調用,為Bean實例初始化之后做一些處理if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}

三級緩存解決循環依賴

循環依賴

在A創建的過程中,A的屬性B需要注入屬性A

  • singletonObjects(一級緩存)
  • earlysingletonObjects(二級緩存)
  • singletonFactories(三級緩存)
  • private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
    private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
  1. 創建的A放入 Set singletonsCurrentlyInCreation(只要創建就放入set,表示bean正在初始化)
  2. 首先是實例化,new 普通對象,addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));為了防止循環引用,盡早持有對象的引用,第二個參數是一個lamda表達式可用來獲取普通對象
  3. 在A填充B時,B需要注入A,判斷A正在初始化,此時出現循環依賴
  4. 先向二級緩存里查找,在多方循環中保證創建的是都是同一個代理對象A
  5. 再向三級緩存里查找,沒有則執行lamda獲取普通對象,并且進行AOP,生成代理對象
  6. 放入bean到二級緩存中
  7. 填充其他的屬性
  8. 進行Aop的邏輯,若是循環依賴則會提前進行Aop(step5)而不是現在
  9. 在二級緩存里查找,是不是已經有已經生成好的bean
  10. 添加到單例池
  11. Set中removeA,標識初始化完成

beanFactory

image-20230816230618815

四個Applicationcontext

FileSystemXmlApplicationContext

ClassPathXmlApplicationContext

AnnotationConfigApplicationContext

AnnotationConfigWebApplicationContext

GenericApplicationContext(是一個干凈的容器)

后置處理器(PostProcessor)

CommonAnnotationBeanPostProcessor

Ordered.LOWEST_PRECEDENCE - 3

@Resource @PostConstruct @PreDestroy

解析WebService關于JAX-WS的相關注解,EJB相關的注解

AutowiredAnnotationBeanPostProcessor

Ordered.LOWEST_PRECEDENCE - 2

處理@Autowire注解,@Value注解,處理javax.inject.Inject JSR-330注解

	//處理類中的屬性@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {//獲取指定類中autowire相關注解的元信息InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);try {//對Bean的屬性進行自動注入metadata.inject(bean, beanName, pvs);}catch (BeanCreationException ex) {throw ex;}catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);}return pvs;}

image-20230818000115153

BeanPostProcessor

處理器定義了Bean 初始化 前后執行的方法。

public interface BeanPostProcessor {//自定義初始化方法之前執行@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}//自定義初始化方法之后執行@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}

InstantiationAwareBeanPostProcessor

該處理器定義了Bean 實例化 前后執行的方法。

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {//實例化之前@Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { //這里可以自定義代理類return null;}//實例化后-但是執行在初始化之前default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}//處理bean的Properties值@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}}

image-20230817234200283

DestructionAwareBeanPostProcessor

該處理器了銷毀Bean之前的操作。

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {//bean銷毀之前void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;//bean是否需要銷毀default boolean requiresDestruction(Object bean) {return true;}}

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

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

相關文章

利用vue-router跳轉的幾種方式

?1 <router-link> 2 this.$router.push 跳轉到指定路徑&#xff0c;并將跳轉頁面壓入history棧中&#xff0c;也就是添加了一個頁面記錄。3 this.$router.replace 跳轉到指定路徑&#xff0c;將history棧中的當前頁面替換為跳轉到的頁面。4 this.$router.go(n) 在his…

數據生成 | MATLAB實現WGAN生成對抗網絡數據生成

數據生成 | MATLAB實現WGAN生成對抗網絡數據生成 目錄 數據生成 | MATLAB實現WGAN生成對抗網絡數據生成生成效果基本描述程序設計參考資料 生成效果 基本描述 1.WGAN生成對抗網絡&#xff0c;數據生成&#xff0c;樣本生成程序&#xff0c;MATLAB程序&#xff1b; 2.適用于MATL…

從public static void main(String[] args)看如何構造數據

java語言中public static void main(String[] args)里面的ages有什么作用&#xff1f; 在Java語言中&#xff0c;public static void main(String[] args) 是一個特殊的方法&#xff0c;它是Java程序的入口點。當你運行一個Java程序時&#xff0c;程序會從這個方法開始執行。這…

【游戲評測】河洛群俠傳一周目玩后感

總游戲時長接近100小時&#xff0c;剛好一個月。 這兩天費了點勁做了些成就&#xff0c;刷了等級&#xff0c;把最終決戰做了。 總體感覺還是不錯的。游戲是開放世界3D游戲&#xff0c;Unity引擎&#xff0c;瑕疵很多&#xff0c;但勝在劇情扎實&#xff0c;天賦系統、秘籍功法…

kubernetes(二)

文章目錄 1. kubernetes常用資源1.1 deployment資源1.2 deployment升級和回滾1.3 tomcat連接mysql1.4 wordpress 2. kubernetes的附加組件2.1 kubernetes集群配置dns服務2.2 kubernetes的dns配置文件2.3 namespace命名空間2.4 kubernetes健康檢查2.4.1 健康檢查livenessprobo2.…

代碼隨想錄二刷day01

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、704. 二分查找二、35. 搜索插入位置三、34. 在排序數組中查找元素的第一個和最后一個位置四、69. x 的平方根五、367. 有效的完全平方數六、27. 移除元素七…

JDBC Vertica Source Connector 使用文檔

支持以下引擎 Spark Flink SeaTunnel Zeta 關鍵特性 批處理 精確一次性處理 列投影 并行處理 支持用戶自定義拆分 支持查詢 SQL 并實現投影效果 描述 通過 JDBC 讀取外部數據源數據。 支持的數據源信息 DatasourceSupported versionsDriverUrlMavenVerticaDifferent depen…

40、端口號和套接字

經過了上節的學習之后&#xff0c;接下來我們再要了解的一個知識就是端口號和套接字。尤其端口號&#xff0c;是傳輸層中最為重要的基礎概念之一&#xff0c;我們在以后的學習中會經常提及到端口號。 端口號 曾經在學習TCP/IP模型的時候&#xff0c;我們曾學過“SAP”即服務訪…

設計HTML5表格

在網頁設計中&#xff0c;表格主要用于顯示包含行、列結構的二維數據&#xff0c;如財務表格、調查數據、日歷表、時刻表、節目表等。在大多數情況下&#xff0c;這類信息都由列標題或行標題及數據構成。本章將詳細介紹表格在網頁設計中的應用&#xff0c;包括設計符合標準化的…

【第七講---視覺里程計1】

視覺里程計就是通過對圖像進行特征提取與匹配得到兩幀之間的位姿&#xff0c;并進行估計相機運動。 經典SLAM中以相機位姿-路標來描述SLAM過程 特征提取與匹配 路標是三維空間中固定不變的點&#xff0c;可以在特定位姿下觀測到在視覺SLAM中&#xff0c;可利用圖像特征點作為…

2023 CCF BDCI 數字安全公開賽正式開啟報名

2023 CCF BDCI 數字安全公開賽重磅來襲&#xff01; 全新的賽道場景 豐厚的賽事獎勵 精彩的周邊活動 數字安全守護人的狂歡盛宴 快來報名參加吧 大賽背景 伴隨著數智化的持續加深&#xff0c;網絡安全、數據安全風險遍布于所有場景之中&#xff0c;包括工業生產、能源、交…

2019年9月全國計算機等級考試真題(C語言二級)

2019年9月全國計算機等級考試真題&#xff08;C語言二級&#xff09; 第1題 1、“商品”與“顧客”兩個實體集之間的聯系一般是 A. 一對一 B. 一對多 C. 多對一 D. 多對多 正確答案&#xff1a;D 第2題 定義學生選修課程的關系模式&#xff1a;SC&#xff08;S#&#xff0c…

tensorboard報錯:AttributeError: module ‘distutils‘ has no attribute ‘version‘

1、報錯問題 環境&#xff1a;pytorch 1.10 tensorboard報錯&#xff1a;AttributeError: module ‘distutils‘ has no attribute ‘version‘ 2、解決 pip uninstall setuptools pip install setuptools59.5.0

運營商三要素 API:構建安全高效的身份驗證系統

當今數字化的世界中&#xff0c;身份驗證是各行各業中至關重要的一環。為了保護用戶的隱私和數據安全&#xff0c;企業需要尋求一種既安全可靠又高效便捷的身份驗證方式。運營商三要素 API 應運而生&#xff0c;為構建安全高效的身份驗證系統提供了有力的解決方案。 運營商三要…

R語言 列表中嵌套列名一致的多個數據框如何整合為一個數據框

在批量建模后容易得到list&#xff0c;list中的每個元素都是單個的tibble 或者 dataframe&#xff0c;如何將這些數據整合為一張表呢&#xff1f; 載入R包 library(broom) library(tidyverse) 模擬數據 models <- txhousing %>% group_by(city) %>% do(modlm(lo…

-Webkit-Box 在 Safari 中出現的兼容性問題

一、問題背景&#xff1a; UI要求要實現這樣的效果&#xff0c;使用 display:-webket-box在chrome瀏覽器下完美解決 但是馬上啪啪打臉&#xff0c;在safari瀏覽器下顯示空白 &#xff0c;不能不說瀏覽器之間的兼容性簡直就是天坑 二、解決辦法 通過瀏覽器調試發現原本float的…

使用Pillow對圖像進行變換

使用Pillow對圖像進行變換 from PIL import Image, ImageEnhance# 原圖 image Image.open("1.jpg") image.show()# 鏡像 mirrored_image image.transpose(Image.FLIP_LEFT_RIGHT) mirrored_image.show() mirrored_image.save(mirror_image.jpg)# 旋轉 rotated_imag…

VK36W1D浴缸,潔具高靈敏度電容式單點液體水位檢測觸摸芯片資料介紹

產品品牌&#xff1a;永嘉微電/VINKA 產品型號&#xff1a;VK36W1D 封裝形式&#xff1a;SOT23-6L 產品年份&#xff1a;新年份 &#xff08;C21-163&#xff09; 產品特點&#xff1a;VK36W1D具有1個觸摸檢測通道&#xff0c;可用來檢測水從無到有和水從有到無的動作。該…

一個模型解決所有類別的異常檢測

文章目錄 一、內容說明二、相關鏈接三、概述四、摘要1、現有方法存在的問題2、方案3、效果 五、作者的實驗六、如何訓練自己的數據1、數據準備2、修改配置文件3、代碼優化修改4、模型訓練與測試 七、結束 一、內容說明 在我接觸的缺陷檢測項目中&#xff0c;檢測缺陷有兩種方法…

網絡通信基礎

1.網絡結構模式&#xff08;C/S和B/S&#xff09; (1)C/S結構模式 服務器 - 客戶機&#xff0c;即 Client - Server&#xff08;C/S&#xff09;結構。 優點&#xff1a; 能充分發揮客戶端 PC 的處理能力&#xff0c;很多工作可以在客戶端處理后再提交給服務器&#xff…