色婷婷狠狠18禁久久YY,CHINESE性内射高清国产,国产女人18毛片水真多1,国产AV在线观看

mysql 父子查詢,該如何學習spring源碼以及解析bean定義的注冊

李中冰2年前20瀏覽0評論
mysql 父子查詢,該如何學習spring源碼以及解析bean定義的注冊?

謝謝邀請!我將從以下幾點介紹源碼及Spring是怎樣解析Bean定義并注冊的

目錄:

學習源碼的重要性?

學習Spring源碼需要基礎嗎?

怎樣把Spring源碼在本地運行?

Bean定義的加載過程

bean定義加載的流程圖

總結

學習源碼的重要性?

(1) 可以提升技術功底,Spring源碼也沉淀了很多年,有非常多的精華所在,不管我們什么水平,通過不斷的閱讀源碼,能對我們的技術有很大的提升,并且工作中遇到類似問題的時候,可以借鑒源碼中是怎么處理的。

(2) 深度的掌握技術框架:源碼看多了,對于新的框架的學習和掌握都是很快的,看下框架的demo,就知道底層是怎么實現的。

比如,學習了Spring 中的AOP,就知道底層是用了JDK的動態代理。然后我們學習mybatis的時候,就在想Mybatis 為什么Service可以直接嗲用Dao接口,就可以直接查詢數據庫了呢 ?其實也是Spring底層對給接口做了動態代理。

(3) 對線上的問題可以進行快速的定位: 當生產上遇到問題時,能夠快速的進行定位,這個能力可以快速秒殺別人。

(4) 對面試有很大的好處,特別是BAT大廠,一般都是問道源碼級別的,你如果不會,可能第一輪就會被刷掉。

學習Spring源碼需要基礎嗎?

答案是肯定的,需要,那么需要哪些基礎呢?

(1)Java 的技術功能

(2) 反射

(3) 設計模式: 簡單工廠、工廠方法、單例模式、原型模式、代理模式、策略模式、模板方法模式、委派模式、適配器模式、裝飾器模式、觀察者模式

(4) Lambda表達式的知識

怎樣把Spring源碼在本地運行?

(1) git clone https://github.com/spring-projects/spring-framework.git

(2) gradle下載,gradle需要JDK8版本

(3) 到下載的spring源碼路徑執行gradle命令,gradlew :spring-oxm:compileTestJava

(4) 用idea打開spring源碼工程,在idea中安裝插件kotlin,重啟idea

(5) 把編譯好的源碼導入到工程中

Bean定義的加載過程

1、首先找到程序的入口

① 找到其構造方法:

② 調用 AnnotationConfigApplicationContext 構造方法,最終會調用父類 GenericApplicationContext的無參方法

③ 調用父類 AnnotationConfigApplicationContext 無參構造方法,生成bean定義讀取器和Bean定義掃描器

上面方法的功能是: 實例化注解的Bean定義掃描器,定義類類路徑下的bean定義掃描器

3.1 為Bean定義讀取器賦值

3.1.1 為容器 中注冊系統的Bean定義信息

上面代碼主要是注冊系統的Bean定義信息,包含以下幾種:

① ConfigurationClassPostProcessor

是一個BeanFactory的后置處理器,主要功能是參與BeanFactory的構建,在這個類中,會解析@Configuration的配置類,解析@ComponentScan、@ComponentScans注解掃描的包,以及解析@Import等注解。

② AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor 實現了BeanPostProcessor,當Spring容器啟動的時候,AutowiredAnnotationBeanPostProcessor 將掃描Spring容器中的所有Bean,當發現Bean中擁有

@Autowired 注解的時候就會找到與其匹配的Bean,并注入到對應的中去。

那么在什么時候調用的呢?我們可以看下debug堆棧;

③ RequiredAnnotationBeanPostProcessor

RequiredAnnotationBeanPostProcessor 是BeanPostProcessor實現.的,注釋應用于bean屬性的setter方法,它表明 受影響的bean 屬性在配置時是否必須,如果配置了,沒有此bean,則容器就會拋出一個BeanInitializationException 異常。

④ .CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor 這個BeanPostProcessor 通過繼承 InitDestroyAnnotationBeanPostProcessor 對 @PostConstruct 和 @PreDestroy注解的支持,以及對bean的依賴注入@Resource的支持。

⑤ EventListenerMethodProcessor

使用EventListenerMethodProcessor處理器來解析方法上的 @EventListener;

執行時機: 實在所有Bean都實例化以后執行的

④ 創建類路徑下的bean定義掃描器

上述方法 是注冊默認的掃描規則

⑤ 讀取配置類

上述方法annotatedClasses為我們配置的mainConfig

annotatedClasses 就是MainConfig

此時上面主要解析 MainConfig,解析成BeanDefinition對象

上述的字段都是什么意思呢?

id: Bean的唯一標識名name: 用來為id 創建一個或者多個別名。class : 用來定義類的全限定名(包名 + 類名)parent: 子類bean定義它所引用它的父類的bean。abstract : 默認為false,用來定義bean是否為抽象bean,它表示這個Bean將不會被實例化,一般用于父類Bean,因為父類bean主要供子類bean繼承使用。lazy-init: 用來定義這個bean是否實現懶初始化。如果為true,它將在BeanFactory啟動時初始化所有的單例bean,反之,如果為false,它只在Bean請求使用時才開始創建SingletonBean。autowired : 自動裝配,它定義了Bean 的自動裝配方式。depends-on:依賴對象:這個Bean在初始化時依賴的對象,這個對象會在這個Bean初始化之前創建。init-method: 用來定義Bean的初始化方法,它會在Bean組裝之后調用,它必須是一個無參的構造 方法。destroy-method: 用來定義Bean的銷毀方法,它在BeanFactory關閉時調用。同樣,它也必須是一個無參 的構造方法。只能適用于單例Bean.factory-method: 定義創建該Bean對象的 工廠方法。factory-bean:定義創建該 Bean對象的工廠類。

那么 BeanDefinitionHolder 又是什么意思呢?

BeanDefinitionHolder 只是封裝了BeanDefinition對象,并且添加了beanName 和 alias 屬性。

為什么這樣設計呢?因為 我們定義bean時,可以定義多個別名的。

BeanDefinitionRegistry 又是什么呢?

BeanDefintion屬性來看,我們并沒有看到id 和 name屬性沒有體現在定義中,原因是ID其左右當前Bean的存儲key注冊到BeanDefinitionRegistry注冊器中。name作為別名key注冊到AliasRegistry注冊中心。最后都是指向其對應的BeanDefinition。

2、AnnotatedBeanDefinitionReader(Bean定義讀取)

BeanDefinition 中存儲了Bean的信息,而BeanDefintiionRegistry是基于ID和name保存了Bean的定義。從Bean到BeanDefinition然后再注冊到BeanDefintionRegistry整個過程。

從上圖看出Bean的定義是由AnnotatedBeanDefinitionReader從@Bean的注解中構建出的,然后基于別名注冊到BeanDefinitionRegistry。

BeanDefintionReader 的結構圖如下:

2.1 bean定義的加載過程

(1) org.springframework.context.support.AbstractApplicationContext#refresh

注冊Bean的 代碼

invokeBeanFactoryPostProcessors(beanFactory);

(2) org.springframework.context.support.AbstractApplicationContext

#invokeBeanFactoryPostProcessors

然后實例化 容器初始化 的 ConfigurationClassPostProcessor Bean,然后調用其 的postProcessBeanDefinitionRegistry方法

BeanDefinitionRegistryPostProcessor 這個接口的調用分為三部分:

(1) 調用實現PriorityOrdered 排序接口

(2) 調用實現了Ordered排序接口

(3) 沒有實現接口的調用

這個接口的理解如下: 獲取BeanDefinition 對象,獲取到這個對象就可以獲取這個對象中注冊的 所有BeanDefiniton對象,我們擁有這個對象后,我們就可以對里面所有的BeanDefinition 對象進行修改。

org.springframework.context.annotation.ConfigurationClassPostProcessor

#postProcessBeanDefinitionRegistry 方法

最終調用

org.springframework.context.annotation.ConfigurationClassParser

最終調用 org.springframework.context.annotation.ConfigurationClassParser

#doProcessConfigurationClass 方法

下面方法主要功能如下:

解析 @PropretySource注解解析@ComponentScan注解解析@Import解析@ImportResource解析@Bean methods處理其他bean定義加載的流程圖總結

Spring 對注解的處理有兩種方式:

1、直接將注解Bean注冊到容器中

可以在初始化容器的時候注冊,也可以在容器創建之后手動調用注冊方法向容器中注冊,然后通過手動刷新容器,使得容器對注冊的注解Bean進行處理

2、通過掃描指定的 包及其子包下的所有類

在初始化注解容器的時指定要自動掃描的路徑。如果容器創建以后,如果再向容器中添加注解Bean,則 需要手動調用容器掃描的方法,然后手動刷新容器,使得容器對所注冊的Bean進行處理。