Spring對註解(Annotation)處理原始碼分析1——掃描和讀取Bean定義
1.從Spring2.0以後的版本中,Spring也引入了基於註解(Annotation)方式的配置,註解(Annotation)是JDK1.5中引入的一個新特性,用於簡化Bean的配置,某些場合可以取代XML配置檔案。開發人員對註解(Annotation)的態度也是蘿蔔青菜各有所愛,個人認為註解可以大大簡化配置,提高開發速度,同時也不能完全取代XML配置方式,XML 方式更加靈活,並且發展的相對成熟,這種配置方式為大多數 Spring 開發者熟悉;註解方式使用起來非常簡潔,但是尚處於發展階段,XML配置檔案和註解(Annotation)可以相互配合使用。
SpringIoC容器對於類級別的註解和類內部的註解分以下兩種處理策略:
(1).類級別的註解:如@Component、@Repository、@Controller、@Service以及JavaEE6的@ManagedBean和@Named註解,都是新增在類上面的類級別註解,Spring容器根據註解的過濾規則掃描讀取註解Bean定義類,並將其註冊到Spring IoC容器中。
(2).類內部的註解:如@Autowire、@Value、@Resource以及EJB和WebService相關的註解等,都是新增在類內部的欄位或者方法上的類內部註解,SpringIoC容器通過Bean後置註解處理器解析Bean內部的註解。
下面將根據這兩種處理策略,分別分析Spring
2.AnnotationConfigApplicationContext對註解Bean初始化:
Spring中,管理註解Bean定義的容器有兩個:AnnotationConfigApplicationContext和
AnnotationConfigWebApplicationContex。這兩個類是專門處理Spring註解方式配置的容器,直接依賴於註解作為容器配置資訊來源的IoC容器。
AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,兩者的用法以及對註解的處理方式幾乎沒有什麼差別,因此本文將以
AnnotationConfigApplicationContext的原始碼如下:
(1).直接將註解Bean註冊到容器中:
可以在初始化容器時註冊;也可以在容器建立之後手動呼叫註冊方法向容器註冊,然後通過手動重新整理容器,使得容器對註冊的註解Bean進行處理。
(2).通過掃描指定的包及其子包下的所有類:
在初始化註解容器時指定要自動掃描的路徑,如果容器建立以後向給定路徑動態添加了註解Bean,則需要手動呼叫容器掃描的方法,然後手動重新整理容器,使得容器對所註冊的Bean進行處理。
接下來,將會對兩種處理方式詳細分析其實現過程。
當建立註解處理容器時,如果傳入的初始引數是具體的註解Bean定義類時,註解容器讀取並註冊。
(1).AnnotationConfigApplicationContext通過呼叫註解Bean定義讀取器AnnotatedBeanDefinitionReader的register方法向容器註冊指定的註解Bean,註解Bean定義讀取器向容器註冊註解Bean的原始碼如下:
從上面的原始碼我們可以看出,註冊註解Bean定義類的基本步驟:
a,需要使用註解元資料解析器解析註解Bean中關於作用域的配置。
c,使用AnnotationConfigUtils的applyScopedProxyMode方法建立對於作用域的代理物件。
d,通過BeanDefinitionReaderUtils向容器註冊Bean。
下面我們繼續分析這3步的具體實現過程
(2).AnnotationScopeMetadataResolver解析作用域元資料:
AnnotationScopeMetadataResolver通過processCommonDefinitionAnnotations方法解析註解Bean定義類的作用域元資訊,即判斷註冊的Bean是原生型別(prototype)還是單態(singleton)型別,其原始碼如下:
上述程式碼中的annDef.getMetadata().getAnnotationAttributes方法就是獲取物件中指定型別的註解的值。
AnnotationConfigUtils類的processCommonDefinitionAnnotations在向容器註冊Bean之前,首先對註解Bean定義類中的通用Spring註解進行處理,原始碼如下:
(4).AnnotationConfigUtils根據註解Bean定義類中配置的作用域為其應用相應的代理策略:
AnnotationConfigUtils類的applyScopedProxyMode方法根據註解Bean定義類中配置的作用域@Scope註解的值,為Bean定義應用相應的代理模式,主要是在Spring面向切面程式設計(AOP)中使用。原始碼如下:
這段為Bean引用建立相應模式的代理,如果在Spring面向切面程式設計(AOP)中涉及到再詳細分析,這裡不做深入的分析。
BeanDefinitionReaderUtils向容器註冊載入的Bean我們在第4篇部落格中已經分析過,主要是校驗Bean定義,然後將Bean新增到容器中一個管理Bean定義的HashMap中,這裡就不做分析。
4.AnnotationConfigApplicationContext掃描指定包及其子包下的註解Bean:
當建立註解處理容器時,如果傳入的初始引數是註解Bean定義類所在的包時,註解容器將掃描給定的包及其子包,將掃描到的註解Bean定義載入並註冊。
(1).Spring中常用的註解:
a.Component註解:
c.Controller註解:
通過分析Spring這4個常用的註解原始碼,我們看到:@Service、@Controller和@Repository註解都添加了一個@Component註解,因此他們都屬於@Component
註解。
(2).ClassPathBeanDefinitionScanner掃描給定的包及其子包:
AnnotationConfigApplicationContext通過呼叫類路徑Bean定義掃描器ClassPathBeanDefinitionScanner掃描給定包及其子包下的所有類,主要原始碼如下:
類路徑Bean定義掃描器ClassPathBeanDefinitionScanner主要通過findCandidateComponents方法呼叫其父類ClassPathScanningCandidateComponentProvider類來掃描獲取給定包及其子包下的類。
(3).ClassPathScanningCandidateComponentProvider掃描給定包及其子包的類:
ClassPathScanningCandidateComponentProvider類的findCandidateComponents方法具體實現掃描給定類路徑包的功能,主要原始碼如下:
5.AnnotationConfigWebApplicationContext載入註解Bean定義:
AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的Web版,它們對於註解Bean的註冊和掃描是基本相同的,但是AnnotationConfigWebApplicationContext對註解Bean定義的載入稍有不同,AnnotationConfigWebApplicationContext注入註解Bean定義原始碼如下:
相關推薦
Spring對註解(Annotation)處理原始碼分析1——掃描和讀取Bean定義
1.從Spring2.0以後的版本中,Spring也引入了基於註解(Annotation)方式的配置,註解(Annotation)是JDK1.5中引入的一個新特性,用於簡化Bean的配置,某些場合可以取代XML配置檔案。開發人員對註解(Annotation)的態度也是蘿蔔
Spring對註解(Annotation)處理原始碼分析2——解析和注入註解配置的資源
1.類內部的註解,如:@Autowire、@Value、@Required、@Resource以及EJB和WebSerivce相關的註解,是容器對Bean物件例項化和依賴注入時,通過容器中註冊的Bean後置處理器處理這些註解的。 2.Spring中處理註解的Bean後置處
spring 註解原始碼分析-掃描和讀取bean定義
1.概述 從spring2.0以後的版本中,spring也引入了基於註解方式的配置,註解是jdk1.5中引入的一個新特性,用於簡化Bean的配置,某些場合可以取代xml配置檔案。 Spring IoC容器對於類級別的註解和類內部的註解分以下兩種策略: (1)類級別的註解
Spring原始碼分析(十五)Spring中常用註解使用以及原始碼分析
從Java5.0開始,Java開始支援註解。Spring做為Java生態中的領軍框架,從2.5版本後也開始支援註解。相比起之前使用xml來配置Spring框架,使用註解提供了更多的控制Spring框架的方式。 現在越來越多的專案也都在使用註解做相關的配置,但Spring的註解非常多,相信
MyBatis原始碼閱讀——MyBatis對事務的處理過程分析
事務管理器 在 MyBatis 中有兩種型別的事務管理器(也就是 type=”[JDBC|MANAGED]”): <environments default="development"> <environment id="
電影網站增刪改查 spring boots/MVC/neo4j 原始碼分析-1 前提
前提: idea , maven 專案新增 分模組 各引用大的方面分兩個模組, data M /webui VC: pom.xml for data module <?xml ver
1、Spring原始碼分析1之讀取配置檔案
1、XMLBeanFcatory BeanFactory bf = new XmlBeanFactory(new ClassPa
Netty Pipeline原始碼分析(1)
原文連結:wangwei.one/posts/netty… 前面,我們分析了Netty EventLoop的 建立 與 啟動 原理,接下里我們來分析Netty中另外兩個重要元件—— ChannelHandler 與 Pipeline。Netty中I/O事件的傳播機制均由它負責,下面我們來看看它是如
vue原始碼分析1-new Vue做了哪些操作
首先我們可以看到vue的原始碼在github上有,大家可以克隆下來。 git地址 我們主要看src下的內容。 1.現在我們來分析下 new Vue都做了哪些操作 var app = new Vue({ el: '#app', mounted:{ console.log(t
Java程式設計師從笨鳥到菜鳥之(八十一)細談Spring(十)深入原始碼分析Spring之HibernateTemplate
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
redis原始碼分析1------dict的實現
1. 總體結構 redis的dict就是hash表,使用鏈式結構來解決key值衝突,典型的資料結構 結構體的定義如下: typedef struct dictEntry { void *key; union { void *val; uint64_t
Netty原始碼分析:1.4伺服器啟動流程
第一章節是主要是伺服器啟動的程式碼分析。章節目錄有: |———1.1初始化NioEventLoopGroup |———1.2初始化NioEventLoop |———1.3初始化NioServerSocketChannel |———1.4伺服器啟動流程 為什麼先從初始化開
Netty原始碼分析:1.3初始化NioServerSocketChannel
第一章節是主要是伺服器啟動的程式碼分析。章節目錄有: |———1.1初始化NioEventLoopGroup |———1.2初始化NioEventLoop |———1.3初始化NioServerSocketChannel |———1.4伺服器啟動流程 為什麼先從初始化開
Netty原始碼分析:1.2初始化NioEventLoop
第一章節是主要是伺服器啟動的程式碼分析。章節目錄有: |———1.1初始化NioEventLoopGroup |———1.2初始化NioEventLoop |———1.3初始化NioServerSocketChannel |———1.4伺服器啟動流程 為什麼先從初始化開
Netty原始碼分析:1.1初始化NioEventLoopGroup
第一章節是主要是伺服器啟動的程式碼分析。章節目錄有: |———1.1初始化NioEventLoopGroup |———1.2初始化NioEventLoop |———1.3初始化NioServerSocketChannel |———1.4伺服器啟動流程 為什麼先從初始化開
《2.uboot和系統移植-第5部分-2.5.uboot原始碼分析1-啟動第一階段》
《2.uboot和系統移植-第5部分-2.5.uboot原始碼分析1-啟動第一階段》 第一部分、章節目錄 2.5.1.start.S引入 2.5.2.start.S解析1 2.5.3.start.S解析2 2.5.4.start.S解析3 2.5.5.start.S解析4 2.5.6.s
MyBatis原始碼分析-1-基礎支援層-反射模組-Reflector/ReflectorFactory
本文主要介紹MyBatis的反射模組是如何實現的。 MyBatis 反射的核心類Reflector,下面我先說明它的建構函式和成員變數。具體方法下面詳解。 org.apache.ibatis.reflection.Reflector public class Reflector {
rxjs 原始碼分析1-(fromEvent)
前言 Rxjs是使用 Observables 的響應式程式設計的庫,它使編寫非同步或基於回撥的程式碼更容易。我們現在針對Rxjs 6 來進行原始碼分析,分析其實現的基本原理, 我們可以根據中文文件來學習Rxjs 的基本使用,但是這個文件是Rxjs 5 的版本。其最基本的使用區別如下,Rxjs 6的操作符都放
Spring通過註解annotation方式注入Bean時,採用動態代理,那麼JDK代理和CGLIB代理區別?
切面程式設計是Spring中非常重要的一個模組,切面程式設計的實現原理是動態代理,那麼動態代理又有兩種實現方式:一種方法是直接實現JDK中的InvocationHandler介面,另一種方法是繼承CGLIB。 首先如果不是很清楚兩者的區別的話,記住一般情況下Invocati
Spring-boot mongodb ID自增長註解實現 適用於JDK 1.7和JDK 1.8
開發工具Idea ,JDK1.8 Entity類 SeqInfo.java package com.gl.springbootdao.mongodb.entity; import lombok.Getter; import lombok.Setter; import lombok.T