學習原始碼的第八個月,我成了Spring的開源貢獻者
阿新 • • 發佈:2020-06-03
@[TOC](目錄)
# 我的經歷
關注我的朋友都知道,**關注**兩個字劃重點,要考!
![img](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230748221-3366733.jpg)
我最近一直在寫Spring的文章,而且僅僅是`Spring FrameWork`的文章 ,從最開始的官網入門到現在原始碼的深度分析。主要就是三個系列
**官網入門系列**,[Spring官網讀書筆記](https://blog.csdn.net/qq_41907991/category_9601507.html),這一系列的文章是入門Spring的不二之選,也是後續原始碼閱讀的基礎
**雜談系列**,[Spring雜談](https://blog.csdn.net/qq_41907991/category_9808373.html),這主要是一些補充內容,可以幫助大家更全面學習到Spring中的各個知識點,同時也會分享一些原始碼閱讀技巧,個人學習心得之類的,雜談嘛,就是不知道放哪裡的文章都打算放這裡,比如這篇文章。
![img](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230748564-1447607729.jpg)
**原始碼分析系列**,[Spring原始碼解析](https://blog.csdn.net/qq_41907991/category_9907747.html),該專欄目前正在創作中,相對而言學習難度比較大,而且因為筆者寫的比較細,估計大部分同學看起來會很費勁,不過如果你能認真看完,收穫絕對巨大!當然有不懂得地方也可以給筆者留言,或者關注文章末尾的公眾號。
本文的主要目的是**教(zhuang)學(bi)**
![image-20200602071958918](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230748856-1028194915.jpg)
就是從筆者的實際經驗出發,談一談怎麼成為一個**開源專案的貢獻者**。
我先說說我自己的經歷吧,在創作[上篇文章]()的時候,筆者發現Spring在例項化物件的時候有這麼一段程式碼,在`org.springframework.beans.factory.support.ConstructorResolver#resolveConstructorArguments`方法中
```java
// 本文不探討技術細節,只是為了簡單說明這個問題,所以省略無關程式碼
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
// ....
for (Map.Entry 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這個判斷是有問題的,正確的做法應該是
```java
if (index+1 > minNrOfArgs) {
minNrOfArgs = index + 1;
}
```
當發現這個問題的時候,第一反應就是肯定是我的姿勢不對,錯的怎麼可能是程式碼,肯定是我!
![在這裡插入圖片描述](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230749402-1516297956.jpg)
接下來,我就對這段程式碼進行了慘無人道的除錯,在無數次`debug`後,我發現,這個地方確實有問題!
![image-20200602203349414](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230750087-544929490.jpg)
在確認了這個問題之後,我要思考的就是怎麼把自己的想法反饋給Spring,換而言之,怎麼為偉大的開源來做貢獻呢?正常來要達到這個目的有兩個方式
- 提交issue
- 直接在GitHub上提交PR(pull request)
對應的就是在[GitHub](https://github.com/spring-projects/spring-framework)上點選下圖紅框選中的兩個位置
![image-20200602204827377](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230750581-265016075.jpg)
如果是使用提交issue的方式,相當於給官方團隊提交了一個議題,這個議題可能是你發現程式碼中的某個bug,也可能是你覺得官方的做法不夠好,你有更好的想法等等。感興趣的話,大家可以去看看Spring中現在有哪些還未關閉的issue,說不定其中一個你就能解決呢~!
如果要採用提交PR的方式的話,首先你得將程式碼fork到自己的GitHub中,然後在從自己的GitHub檢出到本地,在本地做完修改後,提交到GitHub倉庫中,最後從自己的GitHub向Spring官方倉庫發起一個PR。
像我的話很早就已經將程式碼fork到了自己GitHub
![image-20200602211528302](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230751813-359985992.jpg)
上圖中的第一個紅框,說明我這個倉庫是從Spring官方fork過來的,第二個紅框就是可以從這裡向Spring官方提交一個PR。關於詳細的如何提交PR,大家可以自行百度,這裡不做詳細的介紹了。
另外,說了這麼多,先給大家看下我提交的issue吧。
issue連結:https://github.com/spring-projects/spring-framework/issues/25130
因為內容也不長,所以我這裡把原文就直接放到下面了
> In `ConstructorResolver`:
>
> ```java
> private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
> ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
> TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
> // ...
>
> for (Map.Entry 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**:
>
> ```java
> 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
>
> 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">
>
>
>
>
>
>
>
>
>
> ```
>
> the `resolveConstructorArguments` method will return 1,but correct answer is 2。
>
> I think the problem arises because of this judgment:
>
> ```java
> if (index > minNrOfArgs) {
> minNrOfArgs = index + 1;
> }
> ```
>
> It might be better to change it to look like this
>
> ```javascript
> if (index + 1 > minNrOfArgs) {
> minNrOfArgs = index + 1;
> }s
> ```
我在提交issue時主要是按照這種思路
1. 首先擺出有問題的程式碼
2. 描述具體的問題,我是直接通過一個例子來描述的
3. 說出自己的建議
這幾天我又多看了看別人提交的issue,對比起來,我覺得至少應該還要新增一點
- 應該要明確的指出具體哪個版本上出現的問題
# 碰到的問題
## 1、擔心鬧烏龍
雖然在之前我已經除錯過了無數次程式碼,但是心裡還是沒譜啊。畢竟我這麼謹(cai)慎(ji)的一個人,萬一被人噴了怎麼辦?不知道你會不會這麼想,反正我當時就是這麼想的,如果你是這麼想的,建議你去看看別人提交的issue。搜尋條件如下
![image-20200602221719579](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230752283-1180007219.jpg)
> is:closed label:"status: invalid"
我覺得你看幾個,自然就有信心了!
## 2、不知道要怎麼提交
每個開源的專案,只要作者希望這個專案越來越好的話,都會詳細的說明如何給這個專案做開源貢獻,Spring肯定也不例外,這裡還是以提交issue為例,當你點選New issue的時候會出現下面這張圖
![image-20200602222421975](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230752583-1029261430.jpg)
在上圖左邊的框裡很明確的告訴了你提交issue應該要注意什麼
- 首先,你應該要去Stack Overflow提問
- 如果是bug,你應該要指明版本以及你想要做什麼
- 如果是一個增強的話,要提供上下文並且描述清楚問題
- 同一個問題,issue跟PR最好只提交一個,因為GitHub認為它們是一樣的,如果你還不能確定的話,先提交一個issue
而右上角還有更加詳細的文件可供參考。
## 3、英文
大家應該看到了,整個issue都是用英文寫的,那麼英文不好怎麼辦呢?這個時候就要掏出我們的神器了
![image-20200602214339837](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230753283-1681332228.jpg)
嗯,就是詞典,筆者習慣是使用有道詞典。我建議英文不好的同學可以這樣,先將整個issue用中文寫好,如果你真的英文一竅不通的話,可以直接通過翻譯軟體逐句翻譯,然後貼上到GitHub上。但是千萬千萬不要使用中文,就像下面這個哥們
issue連結:https://github.com/spring-projects/spring-framework/pull/25127
![image-20200602215146927](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230753985-433423442.jpg)
像這種issue是會被直接打上invalid(不合格)標籤的,你就想想吧,你學不會英文,你指望我們的外國朋友能看懂中文嘛?是我中華上線五千年的文化不夠博大精深嗎?
## 4、擔心問題描述的不清楚
其實這個問題就是因為英文不好衍生出來的。因為英文不好,自然就會擔心我寫的東西他能不能看懂呢?我的建議就是,結合你測試的程式碼去描述問題。你不用去擔心別人看不懂你寫的程式碼,就以我那個issue的處理流程為例吧。
![image-20200602215944850](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230754307-70671019.jpg)
在你剛剛提交issue時,有專門的`issuemaster`(issue管理員)會給你提交的issue打上一個wait-for-triage的標籤,標誌這個issue是待處理的。
隨後我提交的這個issue,就被指派給了`jhoeller`。你要擔心他看不懂程式碼嗎?給你看兩個東西吧
![image-20200602220527438](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230754567-1670929037.jpg)
你知道那個紅框是啥意思嗎?就是說我發現的那個有問題程式碼的類的作者就是他。
再看一張
![image-20200602220833491](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230755394-830944080.jpg)
就是說,`jhoeller`從2003年開始就已經是Spring這個專案的管理者以及釋出經理了。2003年,我還是一個小學生........
![菜](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230755627-351736298.jpg)
所以啊,只要你稍微正常點,基本上人家都能get到你的點。
# 給你的建議
其實筆者從發現這個問題到最終提交issue大概經過了一週時間,期間一直在猶豫要不要提交issue,就是因為上面提到的幾個問題,一直躊躇不前。但是等我下定決心要去做這件事的時候總共就花了幾個小時的時間。包括研究issue提交的規則以及寫一篇英文版的issue。並且我提交issue的第二天就馬上被處理了,並且`jhoeller`在 [f9aae8d](https://github.com/spring-projects/spring-framework/commit/f9aae8dd5a9a325fa9cb3f1a3b5e9081bbe91e65) 這個commit中已經接受我的建議。
所以我要說的就是,
**真正動手的話,不管什麼問題總能找到解決方案**
**而只是停留在空想,在躊躇,你永遠有一堆問題**
**臨淵羨魚,不如退而結網**
以此文與君共勉!
如果本文對你由幫助的話,記得點個贊吧!也歡迎關注我的公眾號,微信搜尋:程式設計師DMZ,或者掃描下方二維碼,跟著我一起認認真真學Java,踏踏實實做一個coder。
![公眾號](https://img2020.cnblogs.com/other/1547369/202006/1547369-20200602230755804-1098131393.jpg)
我叫DMZ,一個在學習路上匍匐前行的小菜鳥!
> 本文由部落格群發一文多發等運營工具平臺 [OpenWrite](https://openwrite.cn?from=article_bottom