學習源碼的第八個月,我成了Spring的開源貢獻者

来源:https://www.cnblogs.com/daimzh/archive/2020/06/02/13034515.html
-Advertisement-
Play Games

@(目錄) 我的經歷 關註我的朋友都知道,關註兩個字劃重點,要考! 我最近一直在寫Spring的文章,而且僅僅是Spring FrameWork的文章 ,從最開始的官網入門到現在源碼的深度分析。主要就是三個系列 官網入門系列,Spring官網讀書筆記,這一系列的文章是入門Spring的不二之選,也是 ...


@目錄

我的經歷

關註我的朋友都知道,關註兩個字劃重點,要考!

img

我最近一直在寫Spring的文章,而且僅僅是Spring FrameWork的文章 ,從最開始的官網入門到現在源碼的深度分析。主要就是三個系列

官網入門系列Spring官網讀書筆記,這一系列的文章是入門Spring的不二之選,也是後續源碼閱讀的基礎

雜談系列Spring雜談,這主要是一些補充內容,可以幫助大家更全面學習到Spring中的各個知識點,同時也會分享一些源碼閱讀技巧,個人學習心得之類的,雜談嘛,就是不知道放哪裡的文章都打算放這裡,比如這篇文章。

img

源碼分析系列Spring源碼解析,該專欄目前正在創作中,相對而言學習難度比較大,而且因為筆者寫的比較細,估計大部分同學看起來會很費勁,不過如果你能認真看完,收穫絕對巨大!當然有不懂得地方也可以給筆者留言,或者關註文章末尾的公眾號。

本文的主要目的是教(zhuang)學(bi)

image-20200602071958918

就是從筆者的實際經驗出發,談一談怎麼成為一個開源項目的貢獻者

我先說說我自己的經歷吧,在創作上篇文章的時候,筆者發現Spring在實例化對象的時候有這麼一段代碼,在org.springframework.beans.factory.support.ConstructorResolver#resolveConstructorArguments方法中

// 本文不探討技術細節,只是為了簡單說明這個問題,所以省略無關代碼	
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
			ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {

      // ....
		for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
			int index = entry.getKey();
			if (index < 0) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Invalid constructor argument index: " + index);
			}
            // 問題就出在這裡
			if (index > minNrOfArgs) {
				minNrOfArgs = index + 1;
			}
       // ..... 

上述代碼中,minNrOfArgs這個變數就是保存方法需要的最小參數個數,但是index是下標索引,索引是從0開始的,如果有下標為n的元素,那麼最小的參數個數應該是n+1嘛,所以if中的邏輯是沒有問題的,但是if這個判斷是有問題的,正確的做法應該是

if (index+1 > minNrOfArgs) {
    minNrOfArgs = index + 1;
}

當發現這個問題的時候,第一反應就是肯定是我的姿勢不對,錯的怎麼可能是代碼,肯定是我!

在這裡插入圖片描述

接下來,我就對這段代碼進行了慘無人道的調試,在無數次debug後,我發現,這個地方確實有問題!

image-20200602203349414

在確認了這個問題之後,我要思考的就是怎麼把自己的想法反饋給Spring,換而言之,怎麼為偉大的開源來做貢獻呢?正常來要達到這個目的有兩個方式

  • 提交issue
  • 直接在GitHub上提交PR(pull request)

對應的就是在GitHub上點擊下圖紅框選中的兩個位置

image-20200602204827377

如果是使用提交issue的方式,相當於給官方團隊提交了一個議題,這個議題可能是你發現代碼中的某個bug,也可能是你覺得官方的做法不夠好,你有更好的想法等等。感興趣的話,大家可以去看看Spring中現在有哪些還未關閉的issue,說不定其中一個你就能解決呢~!

如果要採用提交PR的方式的話,首先你得將代碼fork到自己的GitHub中,然後在從自己的GitHub檢出到本地,在本地做完修改後,提交到GitHub倉庫中,最後從自己的GitHub向Spring官方倉庫發起一個PR。

像我的話很早就已經將代碼fork到了自己GitHub

image-20200602211528302

上圖中的第一個紅框,說明我這個倉庫是從Spring官方fork過來的,第二個紅框就是可以從這裡向Spring官方提交一個PR。關於詳細的如何提交PR,大家可以自行百度,這裡不做詳細的介紹了。

另外,說了這麼多,先給大家看下我提交的issue吧。

issue鏈接:https://github.com/spring-projects/spring-framework/issues/25130

因為內容也不長,所以我這裡把原文就直接放到下麵了

In ConstructorResolver:

private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
			ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
		TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
		// ...

		for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
			int index = entry.getKey();
			if (index < 0) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Invalid constructor argument index: " + index);
			}
			if (index > minNrOfArgs) {
				minNrOfArgs = index + 1;
			}
			// ....
		}
// ....
 return minNrOfArgs;
}

I assume that method resolveConstructorArguments is to resolve contructor arguments in the XML file and return the minimum number of parameters required by contructor 。but if the first parameter is autowired , the second parameter is config by XML file,the method will not work well。

example:

public class FactoryObject {
	
 public DmzService getDmz(String name, int age, Date birthDay, OrderService orderService) {

	public DmzService getDmz(OrderService orderService,String name) {
		
		return new DmzService(orderService,name);
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
	   default-autowire="constructor">
	<bean id="factoryObject" class="com.dmz.spring.first.instantiation.service.FactoryObject"/>

	<bean class="com.dmz.spring.first.instantiation.service.OrderService" id="orderService"/>

	<bean id="dmzService" factory-bean="factoryObject" factory-method="getDmz">
		<constructor-arg index="1"  value="dmz"/>
	</bean>

</beans>

the resolveConstructorArguments method will return 1,but correct answer is 2。

I think the problem arises because of this judgment:

if (index > minNrOfArgs) {
 minNrOfArgs = index + 1;
}

It might be better to change it to look like this

if (index + 1 > minNrOfArgs) {
 minNrOfArgs = index + 1;
}s

我在提交issue時主要是按照這種思路

  1. 首先擺出有問題的代碼
  2. 描述具體的問題,我是直接通過一個例子來描述的
  3. 說出自己的建議

這幾天我又多看了看別人提交的issue,對比起來,我覺得至少應該還要添加一點

  • 應該要明確的指出具體哪個版本上出現的問題

碰到的問題

1、擔心鬧烏龍

雖然在之前我已經調試過了無數次代碼,但是心裡還是沒譜啊。畢竟我這麼謹(cai)慎(ji)的一個人,萬一被人噴了怎麼辦?不知道你會不會這麼想,反正我當時就是這麼想的,如果你是這麼想的,建議你去看看別人提交的issue。搜索條件如下

image-20200602221719579

is:closed label:"status: invalid"

我覺得你看幾個,自然就有信心了!

2、不知道要怎麼提交

每個開源的項目,只要作者希望這個項目越來越好的話,都會詳細的說明如何給這個項目做開源貢獻,Spring肯定也不例外,這裡還是以提交issue為例,當你點擊New issue的時候會出現下麵這張圖

image-20200602222421975

在上圖左邊的框里很明確的告訴了你提交issue應該要註意什麼

  • 首先,你應該要去Stack Overflow提問
  • 如果是bug,你應該要指明版本以及你想要做什麼
  • 如果是一個增強的話,要提供上下文並且描述清楚問題
  • 同一個問題,issue跟PR最好只提交一個,因為GitHub認為它們是一樣的,如果你還不能確定的話,先提交一個issue

而右上角還有更加詳細的文檔可供參考。

3、英文

大家應該看到了,整個issue都是用英文寫的,那麼英文不好怎麼辦呢?這個時候就要掏出我們的神器了

image-20200602214339837

嗯,就是詞典,筆者習慣是使用有道詞典。我建議英文不好的同學可以這樣,先將整個issue用中文寫好,如果你真的英文一竅不通的話,可以直接通過翻譯軟體逐句翻譯,然後粘貼到GitHub上。但是千萬千萬不要使用中文,就像下麵這個哥們

issue鏈接:https://github.com/spring-projects/spring-framework/pull/25127

image-20200602215146927

像這種issue是會被直接打上invalid(不合格)標簽的,你就想想吧,你學不會英文,你指望我們的外國朋友能看懂中文嘛?是我中華上線五千年的文化不夠博大精深嗎?

4、擔心問題描述的不清楚

其實這個問題就是因為英文不好衍生出來的。因為英文不好,自然就會擔心我寫的東西他能不能看懂呢?我的建議就是,結合你測試的代碼去描述問題。你不用去擔心別人看不懂你寫的代碼,就以我那個issue的處理流程為例吧。

image-20200602215944850

在你剛剛提交issue時,有專門的issuemaster(issue管理員)會給你提交的issue打上一個wait-for-triage的標簽,標誌這個issue是待處理的。

隨後我提交的這個issue,就被指派給了jhoeller。你要擔心他看不懂代碼嗎?給你看兩個東西吧

image-20200602220527438

你知道那個紅框是啥意思嗎?就是說我發現的那個有問題代碼的類的作者就是他。

再看一張

image-20200602220833491

就是說,jhoeller從2003年開始就已經是Spring這個項目的管理者以及發佈經理了。2003年,我還是一個小學生........

菜

所以啊,只要你稍微正常點,基本上人家都能get到你的點。

給你的建議

其實筆者從發現這個問題到最終提交issue大概經過了一周時間,期間一直在猶豫要不要提交issue,就是因為上面提到的幾個問題,一直躊躇不前。但是等我下定決心要去做這件事的時候總共就花了幾個小時的時間。包括研究issue提交的規則以及寫一篇英文版的issue。並且我提交issue的第二天就馬上被處理了,並且jhoellerf9aae8d 這個commit中已經接受我的建議。

所以我要說的就是,

真正動手的話,不管什麼問題總能找到解決方案

而只是停留在空想,在躊躇,你永遠有一堆問題

臨淵羡魚,不如退而結網

以此文與君共勉!

如果本文對你由幫助的話,記得點個贊吧!也歡迎關註我的公眾號,微信搜索:程式員DMZ,或者掃描下方二維碼,跟著我一起認認真真學Java,踏踏實實做一個coder。

公眾號

我叫DMZ,一個在學習路上匍匐前行的小菜鳥!

本文由博客群發一文多發等運營工具平臺 OpenWrite 發佈


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 面向介面編程能非常有效地提高代碼質量,可以將介面和實現相分離,封裝不穩定的實現,暴露穩定的介面。上游系統面向介面而非實現編程,不依賴不穩定的實現細節,這樣當實現發生變化的時候,上游系統的代碼基本上不需要做改動,以此來降低耦合性,提高擴展性。 ...
  • 背景 最近瞭解到很多朋友對限流、熔斷、降級、隔離、超時重試的概念和應用場景理解的不是很到位,所以想用五篇的篇幅稍微系統的介紹一下。 本篇是第一篇,是限流做詳解,如果反饋好的話,我會繼續寫下麵四篇。不好的話就算了,算我理解不夠,再自己總結總結。 限流的概念 有朋友問我限流和熔斷有什麼區別,我的理解很簡 ...
  • 老孟導讀:歷時1年的時間,整理完成了330+組件的詳細用法,不僅包含UI組件,還包含了功能性的組件。 雖然整理了 330+的組件基本用法,但並不是讓你每一個都學習一遍,任何技術基本都是掌握 20%就可以解決 80%的問題,因此只需學會基礎組件就可以上手項目了,至於其他的控制項只需大概瀏覽一下,做項目的 ...
  • 19. 文件讀寫 19.1 文件操作 數據持久化,是將程式中的對象以數據的方式保存到磁碟上,在程式下次運行時,可以將數據從磁碟上恢復到記憶體中。數據持久化的方式有很多,而最為常見的方式是將數據以文件的形式保存。在Python中,可以通過內置函數的方法進行文件的讀、寫、刪除等操作。 19.1.1 文件的 ...
  • 18.目錄與文件 18.1 os和shutil 日常使用過程中,難免需要使用跟文件系統相關的標準庫。在使用Python文件系統中,常用的庫為os和shutil標準庫,方法如下所示: import os import shutil 18.1.1 遍歷文件夾 os.getcwd():獲取當前工作目錄,返 ...
  • 1 import tkinter 2 import subprocess 3 import os 4 import time 5 import re 6 import sys 7 from tkinter import Label, Button, StringVar 8 from tkinter. ...
  • 在c/c++中,為瞭解決一些頻繁調用的小函數大量消耗棧空間(棧記憶體)的問題,特別的引入了inline修飾符,表示為內聯函數。 棧空間就是指放置程式的局部數據(也就是函數內數據)的記憶體空間。 在系統下,棧空間是有限的,假如頻繁大量的使用就會造成因棧空間不足而導致程式出錯的問題,如,函數的死迴圈遞歸調用 ...
  • 類規範:包括類聲明以及類方法定義 類聲明提供類的藍圖 方法定義提供細節 常見不通用的約定:類名首字母大寫 類介面: 介面由編寫類的人提供的方法組成。介面讓程式員能夠編寫與類對象交互的代碼,從而讓程式能夠使用類對象。 要使用某個類,必須瞭解其公共介面;要編寫類,必須創建其公共介面。 通常,C++程式員 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...