《Spring 源碼解讀》

《Spring 源碼解讀》

傻瓜源碼-內容簡介

傻瓜源碼-內容簡介
🤪【職場經驗】(持續更新)
精編短文:如何成爲值錢的Java開發-指南

如何平常學習、如何書寫簡歷、引導面試官、系統準備面試、選擇offer、提升績效、晉升TeamLeader.....
🧐【源碼解讀】(持續更新) <br/>1. 源碼選材:Java架構師必須掌握的全部框架和類庫源碼<br/>2. 內容大綱:按照「企業應用Demo」講解執行源碼:總綱「閱讀指南」、第一章「源碼基礎」、第二章「相關Java基礎」、第三章「白話講源碼」、第四章「代碼解讀」、第五章「設計模式」、第六章「附錄-面試習題、相關JDK方法、中文註釋可運行源碼項目」
3. 讀後問題:粉絲羣答疑解惑
已收錄:HashMapReentrantLockThreadPoolExecutor《Spring源碼解讀》《Dubbo源碼解讀》.....
🤩【面試題集】(持續更新)<br/>1. 面試題選材:Java面試常問的全部面試題和必會知識點<br/>2. 內容大綱:第一部分」注意事項「、第二部分「面試題解讀」(包括:」面試題「、」答案「、」答案詳解「、「實際開發解說」)
3. 深度/廣度:面試題集中的答案和答案詳解,都是對齊通常面試要求的深度和廣度
4. 讀後問題:粉絲羣答疑解惑
已收錄:Java基礎面試題集Java併發面試題集JVM面試題集數據庫(Mysql)面試題集緩存(Redis)面試題集 .....
🤤【粉絲羣】(持續更新) <br/>收錄:阿里、字節跳動、京東、小米、美團、嗶哩嗶哩等大廠內推
😛 做者介紹:Spring系源碼貢獻者、世界五百強互聯網公司、TeamLeader、Github開源產品做者
😛 做者微信:wowangle03 (企業內推聯繫我)

  加入個人粉絲社羣,閱讀更多內容。從學習到面試,從面試到工做,從 coder 到 TeamLeader,天天給你答疑解惑,還能有第二份收入!html

圖片

第 1 章 閱讀指南

  • 本書基於 Spring 5.0.x(5.0.16.BUILD-SNAPSHOT)版本。
  • 本書根據」企業應用 Demo 「解讀源碼。
  • 本書建議分爲兩個學習階段,掌握了第一階段,再進行第二階段;java

    • 第一階段,理解章節「源碼解讀」前的全部內容。即掌握 IT 技能:熟悉 Spring 原理。
    • 第二階段,理解章節「源碼解讀」(包括源碼解讀)以後的內容。即掌握 IT 技能:精讀 Spring 源碼。
  • 建議按照本書內容順序閱讀(內容先後順序存在依賴關係)。
  • 閱讀過程當中,若是遇到問題,記下來,後面不遠的地方確定有解答。
  • 閱讀章節「源碼解讀」時,建議得到中文註釋源碼項目配合本書,Debug 進行閱讀學習。
  • 源碼項目中的註釋含義;git

    • 」企業應用 Demo 「在源碼中,會標註「 // Spring Demo 」。
    • 在源碼中的不易定位到的主線源碼,會標註 「 // tofix 主線 」。
  • 如下注釋的源碼,暫時不深刻講解:面試

    • 在執行「企業應用 Demo 」過程當中,沒有執行到的源碼(因爲遍歷空集合、 if 判斷),會標註「 /* Demo不涉及 / 」。
    • 在執行」企業應用 Demo 「過程當中,有用變量的數據轉換方法,輸入值和輸出值相同(因爲遍歷空集合、 if 判斷沒有處理數據),會標註「 /* 無效果 / 」。
    • 從頭至尾都是空的變量(包括不包含元素的集合),會標註「 /* 空變量 / 」。
    • 有被賦值的變量,但「企業應用 Demo 」運行過程當中沒有使用到該變量,會標註」 /* 無用邏輯 / 「。
    • 不是核心邏輯,而且不影響源碼理解,會標註」 /* 非主要邏輯 / 「。
    • 鎖、異常處理邏輯、非空校驗、日誌打印沒有標註註釋 。

第 2 章 Spring 實戰

2.1 源碼本地構建

  1. 下載做者詳細中文註釋後的 Spring 源碼;
  2. 保證本地已經安裝 jdk(最好 1.8)、gradle(最好 4.4.1 版本);
  3. 進入項目根目錄,打開 cmd 或者 git 命令行,輸入 ./gradlew :spring-oxm:compileTestJava 進行編譯,若是中途編譯失敗,就重複編譯幾回;
  4. 而後使用 Idea 導入項目,使用 gradle 進行 import;
  5. 全局搜索「 // Spring Demo 」,運行「企業應用 Demo」。

2.2 基礎入門 Demo

代碼示例 1spring

public class PersionA {
    private PersionB pb;

    public PersionB getPb() {
        return pb;
    }

    public void setPb(PersionB pb) {
        this.pb = pb;
    }
}

代碼示例 2sql

public class PersionB {
    private PersionA pa;

    public PersionA getPa() {
        return pa;
    }

    public void setPa(PersionA pa) {
        this.pa = pa;
    }
}

代碼示例 3 application.xml 配置文件數據庫

<?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"
>
    <bean id="persionA" class="org.springframework.demo.PersionA">
        <property name="pb" ref="persionB"/>
    </bean>
    <bean id="persionB" class="org.springframework.demo.PersionB">
        <property name="pa" ref="persionA"/>
    </bean>

</beans>

代碼示例 4 啓動 Spring 設計模式

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");
        PersionA persion = (PersionA) context.getBean("persionA");
        System.out.println(persion.getPb());
    }
}

2.3 企業應用 Demo

  暫時由「基礎入門 Demo」代替,」企業應用 Demo 「以及配套的第 2 版《Spring 源碼解讀》正在修改中...。緩存

第 3 章 相關 Java 基礎

3.1 實例化接口


代碼示例 1 接口微信

public interface Person {
    public abstract void eat();
}

代碼示例 2 實例化接口

public class Demo {
    public static void main(String[] args) {
        // 使用 Lambda 直接建立 Persion 接口實例
        Person p1 = () -> System.out.println("eat something!");
        // 打印結果:eat something!
        p1.eat();
    }
}

  直接實例化接口適用於在多個不一樣的調用場合,抽象方法會有不一樣實現邏輯的場景。反過來想,若是不使用 Lambda 建立 Persion 接口實例,想要在不一樣調用場合,執行不一樣實現邏輯,就必須爲每一個場合定義一個實現了接口的類,而後在實現類的方法裏實現對應邏輯。這樣比較,使用 Lambda 表達式直接建立接口實例是否是大大簡化了代碼呢!

第 4 章 源碼基礎

4.1 導讀

   1. Spring 中的對象種類

  在」企業應用 Demo「中,有涉及到兩種對象:Pojo、Bo;

  • Pojo(plian ordinary java object):僅包含屬性以及屬性的 get、set、add、remove、is、has 方法的對象;
  • Bo(business object):就是封裝着業務邏輯的對象。

4.2 ClassPathXmlApplicationContext

  ClassPathXmlApplicationContext(Bo),繼承自 AbstractRefreshableConfigApplicationContext ,調用構造函數實例化的同時,啓動了 Spring ;在「企業應用 Demo」中主要負責建立 DefaultListableBeanFactory 工廠對象和 XmlBeanDefinitionReader 對象來執行邏輯。

代碼示例 重要成員變量

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
    
    // 繼承自 AbstractRefreshableConfigApplicationContext
    // configLocations 表示 application.xml 配置文件的路徑,能夠配置多個配置文件,例:["classpath*:applicationContext.xml"]
    private String[] configLocations;
    
    // 繼承自 AbstractRefreshableApplicationContext
    // beanFactory 表示 DefaultListableBeanFactory 實例,總的來講就是用於生成 Bean 的工廠。好比:生成目標對象(例:PersionA)。
    private DefaultListableBeanFactory beanFactory;

4.3 XmlBeanDefinitionReader

  XmlBeanDefinitionReader(Bo),簡稱:XmlBean定義讀取器;負責讀取 application.xml 配置文件,解析成 Resource 實例(Spring 定義的,是用來封裝文件資源的類),再根據 Resource 實例獲取到的 inputStream 輸入流,轉化成 Document 實例;而後交由 DefaultBeanDefinitionDocumentReader 對象進行下一步操做。

代碼示例 重要成員變量

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

    // resourceLoader 表示 ClassPathXmlApplicationContext 實例,負責讀取 applicaiton.xml 文件爲 Resource 實例
    private ResourceLoader resourceLoader;

    // documentLoader 負責將表明 Resource的inputStream輸入流轉換成 Document 對象
    private DocumentLoader documentLoader = new DefaultDocumentLoader();

    // resourcesCurrentlyBeingLoaded 保存當前線程加載了的 application.xml 配置文件(包括<import/> 標籤引進的 xml 資源),用來檢查 <import/> 形成的循環導入
    private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
            new NamedThreadLocal<>("XML bean definition resources currently being loaded");

    // 繼承自 AbstractBeanDefinitionReader
    // registry 表示 DefaultListableBeanFactory 實例,XmlBeanDefinitionReader 是經過構造函數獲取到並持有的這個對象,是爲了向後續邏輯傳遞下去
    private final BeanDefinitionRegistry registry;

4.4 DefaultBeanDefinitionDocumentReader

  DefaultBeanDefinitionDocumentReader(Bo),簡稱:Bean 定義 Document 讀取器;負責讀取 Document 實例中的節點信息,如:< bean/>、< import/> 等;而後交由 BeanDefinitionParserDelegate 對象進行下一步操做。

代碼示例 重要成員變量

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

    // readerContext 表示 XmlReaderContext 實例,Xml讀取器上下文
    // 做用:爲了將 XmlBeanDefinitionReader 實例、 Resource 實例、DefaultListableBeanFactory 實例等 統一封裝到XmlReaderContext 裏,向後傳遞使用
    private XmlReaderContext readerContext;

    // delegate 表明 BeanDefinitionParserDelegate 實例;負責將 Document 對象(例如:< bean/>)裝載爲 GenericBeanDefinition
    private BeanDefinitionParserDelegate delegate;

4.5 BeanDefinitionParserDelegate

  BeanDefinitionParserDelegate(Bo),簡稱:Bean 定義解析代理;負責將 Document 對象(例如:< bean/>)裝載成 GenericBeanDefinition 對象;而後交由 DefaultListableBeanFactory 對象進行下一步操做。

代碼示例 重要成員變量

public class BeanDefinitionParserDelegate {

    // readerContext 表示 XmlReaderContext 實例,上文提過,是Xml讀取器上下文
    // 用於從 XmlReaderContext 裏獲取 DefaultListableBeanFactory 實例等對象)
    private final XmlReaderContext readerContext;

4.6 GenericBeanDefinition

  GenericBeanDefinition(Pojo),簡稱:通用 Bean 定義;是用來裝載 < bean/> 配置的實體類。

代碼示例 重要成員變量

public class GenericBeanDefinition extends AbstractBeanDefinition {

    // beanClass 對應<bean class=""/>中的 class 值,一開始會被賦值爲 class 設置的字符串,後面會被賦值爲解析後的 Class 對象
    private volatile Object beanClass;

    // 繼承自 AbstractBeanDefinition
    // propertyValues 是保存 <property/> 信息的實體類
    private MutablePropertyValues propertyValues;

4.7 BeanDefinitionHolder

  BeanDefinitionHolder(Pojo),簡稱:Bean定義持有者;負責持有 GenericBeanDefinition 對象(也就是說 GenericBeanDefinition 對象是 BeanDefinitionHolder 一個成員變量),在「企業應用 Demo」中,只起到數據傳輸的做用。

  BeanDefinitionHolder 的必要性和 BeanNameAware 相關;」企業應用 Demo「不涉及。

代碼示例 重要成員變量

public class BeanDefinitionHolder implements BeanMetadataElement {

    // beanDefinition 表示 GenericBeanDefinition 實例;用於裝載從 application.xml 配置文件中解析出來的 < bean/> 
    private final BeanDefinition beanDefinition;

    // beanName 表示 <bean/> 在 Spring 中的名字,通常爲 <bean id=""/> 中的 id 值
    private final String beanName;

4.8 DefaultListableBeanFactory

  DefaultListableBeanFactory(Bo);總的來講就是生成 Bean 的工廠。在」企業應用 Demo「中,主要負責根據 GenericBeanDefinition 對象,生成目標對象(例:PersionA)並注入屬性值,放到 Map<String, Object> singletonObjects 裏保存起來,供應用程序使用。

代碼示例 重要成員變量

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    // beanDefinitionNames 用於存放從 application.xml 文件中解析出來的 beanName(通常爲 <bean/>標籤中的 id 值),按註冊順序排列
    private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
    
    // 數據結構:{beanName -> GenericBeanDefinition 對象},用於後續邏輯根據 beanName 獲取 GenericBeanDefinition 實例來用
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    // 繼承自 AbstractBeanFactory
    // 數據結構:{beanName -> RootBeanDefinition 實例} 緩存,用於防止重複建立 beanName 的 RootBeanDefinition
    private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);

    // 繼承自 DefaultSingletonBeanRegistry
    // singletonsCurrentlyInDestruction 用於標記 Spring 是否處在銷燬單例的過程,默認爲false;若是設置爲 true,建立單例bean的時候,就會拋出 BeanCreationNotAllowedException 異常
    private boolean singletonsCurrentlyInDestruction = false;
    
    /**
     * 
     * 如下成員變量,參考下一節「循環依賴」,進行理解
     *
     */

    // 繼承自 DefaultSingletonBeanRegistry
    // singletonsCurrentlyInCreation 中存儲的beanName都是處於建立過程當中的
    // 當該目標對象建立完成後,會將對應的 beanName 從 singletonsCurrentlyInCreation 集合中剔除掉
    // 做用:主要用於解決 IOC 循環依賴的問題
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    // 繼承自 DefaultSingletonBeanRegistry
    // 數據結構:{beanName ->單例 bean 對象(例:PersionA 實例)} ,也被稱爲一級緩存;
    // 添加場景:在「企業應用 Demo」中,當 application.xml 中定義的 bean 對象被徹底實例化後(徹底實例化是指實例化並注入屬性值後),則會被放入本緩存中
    // 做用:單例 bean 會被放到這個緩存裏,當應用系統想要獲得 Spring 管理的 <bean/> 時(例:context.getBean("persion");),就能夠直接從這個緩存裏獲取
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    // 繼承自 DefaultSingletonBeanRegistry
    // 數據結構:{beanName —> ObjectFactory 接口的實現類實例} ,也稱爲三級緩存
    // ObjectFactory 是生產目標對象的工廠接口;不一樣場景下,生成對象的邏輯不一樣,因此這裏使用了工廠接口(好比:生成 AOP 代理對象和經過構造函數生成普通對象等)
    // 添加場景:在「企業應用 Demo」中,當 bean 對象(例:PersionA 實例)實例化後,沒有注入屬性值以前,會放入本緩存;
    // 移除場景:在「企業應用 Demo」中,當 bean 對象徹底實例化後,則會從本緩存中剔除掉
    // 做用:在「企業應用 Demo」中,singletonObjects 存放的 value 值是 lambda 表達式建立的 ObjectFactory 接口實例;
    // singletonFactories 是建立目標對象過程當中,用於存放處於中狀態對象的臨時容器
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    // 繼承自 DefaultSingletonBeanRegistry
    // 數據結構:{beanName -> bean 對象(例:PersionA 實例)} ,是提早曝光的單例對象緩存,也稱爲二級緩存;
    // 添加場景:在「企業應用 Demo」中,當 bean 對象(例:PersionA 實例)實例化後,發現成員變量指定了其它 Spring 管理的 <bean/> 對象(例:PersionB 實例),而且這個 <bean/> 對象(例:PersionB 實例)存在於 singletonsCurrentlyInCreation ,也存在於三級緩存中,就會把 PersionB 對象從三級緩存中移除,放到二級緩存裏;(若是未發生過循環依賴的場景,二級緩存從始至終沒有存在過值)
    // 移除場景:在「企業應用 Demo」中,當 bean 對象徹底實例化後,則會從本緩存中剔除掉
    // 做用:用於解決 IOC 循環依賴的問題
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

4.9 循環依賴

1. 問題

  若是 persionA 依賴 persionB ,persionB 依賴 persionA ,Spring 是如何初始化 PersionA 和 PersionB 的?(這個現象稱之爲」循環依賴「)

2. 答案

persionA persionB
1.要開始建立 persionA 對象以前,向 singletonsCurrentlyInCreation 添加該對象的對應 beanName(旨在標記 persionA 處於’建立中‘)
2.建立完 persionA 對象後,再把persionA 對象存在三級緩存中,再準備開始注入屬性
3.注入屬性時,發現依賴 persionB ,要建立 persionB 對象
總結:這時,persionA 對象的 pb 屬性爲空;三級緩存包含 persionA
1.要開始建立 persionB 對象以前,向 singletonsCurrentlyInCreation 添加該對象的對應 beanName(旨在標記 persionB 處於’建立中‘)
2.建立完 psersionB 對象後,再把 persionB 對象存在三級緩存裏,再準備開始注入屬性
2.注入屬性時,發現依賴 persionA 對象
3.建立 persionA,發現 singletonsCurrentlyInCreation 存有相應 beanName(PersionA 處於'建立中' ),而且保存在三級緩存裏,則直接從三級緩存中移除 PersionA 對象,而後放到二級緩存裏
4.將 persionA 對象注入到 persionB 對象的 pa 屬性裏
5.從三級緩存中刪掉 persionB 對象,放到一級緩存裏
總結:這時,persionB 對象的 pa 屬性不爲空,可是 pa 屬性(persionA)的 pb 屬性爲空;二級緩存包含 persionA,一級緩存包含 persionB
4.得到 persionB 對象,放到 pb 屬性裏
5.從二級緩存中刪掉 persionA對象,放到一級緩存裏
總結:這時,persionA 對象的 pb 屬性不爲空,pb 屬性的 pa 屬性也不爲空;一級緩存包含 persionA 和 persionB

4.10 RootBeanDefinition

  RootBeanDefinition(Pojo); < bean/> 有繼承的能力(< bean parent=""/> ),因此 Spring 會進行對父子 < bean/> 進行合併操做,最後合併成 RootBeanDefinition 實例,區別於 GenericBeanDefinition 實例 。

代碼示例 重要成員變量

public class RootBeanDefinition extends AbstractBeanDefinition {

    // beanClass 表示 <bean class="org.springframework.PersionA"/> 中的 class 值,一開始爲"org.springframework.PersionA"字符串,而後會解析爲 PersionA Class 對象,再 set 到當前屬性裏
    private volatile Object beanClass;

    // 繼承自 AbstractBeanDefinition
    // propertyValues 表示對應 < property/> 信息的實體類
    private MutablePropertyValues propertyValues;

    // scope 表示 <bean/> 的單例模式;scope 默認爲"",當 Spring 發現值是空字符串時,而且用戶沒有指定,就會將值修改成"singleton"(單例),也就是說 Spring 的 <bean/> 默認是單例的。
    private String scope = "";

4.11 MutablePropertyValues

  MutablePropertyValues(Pojo),在 Spring 中,用於封裝 < property/> 信息的實體類。

代碼示例 重要成員變量

public class MutablePropertyValues implements PropertyValues, Serializable {

    // propertyValueList 表示 <property/> 集合(集合中的一個元素對應一個<property/>標籤)
    private final List<PropertyValue> propertyValueList;

4.12 PropertyValue

  PropertyValue(Pojo),在 Spring 中,對應 < property/> 的實體類,保存了 < property/> 的配置信息,好比屬性名、屬性值等;這裏 Spring 之因此不使用 Map 這種鍵值對類,是由於自定義類有更強的擴展性。

代碼示例 重要成員變量

public class PropertyValue extends BeanMetadataAttributeAccessor implements Serializable {

    // name 表示 <property/> 中的 name 屬性
    private final String name;

    // value 表示 <property/> 指定的值;例:<property name="persionB" ref="pB">,value一開始爲指代 ref 的 RuntimeBeanReference 對象;後續邏輯將 RuntimeBeanReference 對象解析爲 PersionB 對象,從新覆蓋到 value 屬性上
    private final Object value;

    // source 是 PropertyValue 實例;在將 RuntimeBeanReference 對象解析爲 PersionB對象以前和以後,分別會使用兩個 PropertyValue 對象去裝載,這個 source 屬性就是以前的 PropertyValue 對象(例:<property name="persionB" ref="pB">)
    private Object source;

    // conversionNecessary 表示是否轉換 <Property/> 指定的值,默認爲空(表示有必要進行轉換),Spring就會查找用戶自定義的轉換器進行轉換,當發現沒有轉換器,就會將 conversionNecessary 設置爲 false ,不須要轉換
    volatile Boolean conversionNecessary;

4.13 RuntimeBeanReference

  RuntimeBeanReference(Pojo),在 Spring 中,用於裝載 < property ref=""/> 中 ref 指定的值。

代碼示例 重要成員變量

public class RuntimeBeanReference implements BeanReference {

    // beanName 表示 ref 的值
    private final String beanName;

4.14 BeanWrapperImpl

  BeanWrapperImpl(Bo),持有目標對象(例:PersionA 對象),能夠對其設置/獲取屬性的描述信息,好比:查詢只讀/可寫屬性等。」企業應用 Demo」中,主要負責給 < bean/> 實例化後的目標對象(例:PersionA 對象)注入的 < property/> 所配置的值。

代碼示例 重要成員變量

public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements BeanWrapper {

    // 繼承自 AbstractNestablePropertyAccessor
    // wrappedObject 表示 <bean/> 所表明的目標對象,例:PersionA 對象
    Object wrappedObject;

    // 私有類
    // BeanPropertyHandler 表示通用屬性描述器,用於保存 < property/> 中的相關信息(例:屬性所屬類 Class 、屬性對應 get/set 方法 Method 對象等);」企業應用 Demo」中,主要用於從本對象獲取相應屬性的set方法 Method 對象
    private class BeanPropertyHandler extends PropertyHandler{...}

4.15 BeanWrapperImpl$BeanPropertyHandler

  BeanWrapperImpl$BeanPropertyHandler(Bo)($ 表示 BeanPropertyHandler 是 BeanWrapperImpl 中的內部類),Bean屬性處理器,負責管理 < property/> 屬性;」企業應用 Demo」中,主要負責利用反射,調用 setter 方法,對 < bean/> 設置 < property /> 指定的值。

代碼示例 重要成員變量

public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements BeanWrapper {
    
private class BeanPropertyHandler extends PropertyHandler {

    // GenericTypeAwarePropertyDescriptor 實例,繼承自 PropertyDescriptor(來自第三方jar包),能夠得到類的信息,比 setter 方法、setter 方法的參數類型等
    private final PropertyDescriptor pd;

4.16 GenericTypeAwarePropertyDescriptor

  GenericTypeAwarePropertyDescriptor(Pojo), 通用屬性描述器,用於保存 < property/> 中的相關信息(例:屬性所屬類 Class 、屬性的對應 get/set 方法 Method 對象等);」企業應用 Demo」中,主要用於從本對象獲取相應屬性的 set 方法 Method 對象。

代碼示例 重要成員變量

final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {

    // beanClass 表示 <property/> 的所屬類的 Class 對象(例:PersionA.Class)
    private final Class<?> beanClass;

    // 繼承自 PropertyDescriptor(第三方jar)
    // writeMethodRef 記錄了 <bean/> 對象(例:PersionA )的 set<property/> 的 Method 對象,用於獲取 set 方法反射設置屬性值
    private final MethodRef writeMethodRef = new MethodRef();

    // writeMethod 表示 setter 方法的 Method 對象
    private final Method writeMethod;

    // propertyType 表示 <property/> 指代值的 Class 對象
    private Class<?> propertyType;

<br/>

加入個人粉絲社羣,閱讀所有內容

  從學習到面試,從面試到工做,從 coder 到 TeamLeader,天天給你答疑解惑,還能有第二份收入,這樣的知識星球,難道你還要猶豫!

圖片

相關文章
相關標籤/搜索