spring-core源碼分析

概述


org.springframework.context.ApplicationContext接口是Spring IoC的容器,負(fù)責(zé)bean的初始化,配置和裝配。ApplicationContext通過讀取元數(shù)據(jù)(configuration metadata)獲取該把bean注入到哪個(gè)對象皆辽。元數(shù)據(jù)可以是XML, Java注解或Java代碼。
  Spring提供了幾種ApplicationContext的實(shí)現(xiàn)芥挣。本地化項(xiàng)目使用的ClassPathXMLApplicationContext或FileSystemXMLApplicationContext. 然而XML是比較傳統(tǒng)的配置方式驱闷,使用注解或代碼配合少量XML作為元數(shù)據(jù)可以使配置更精簡。
   在大多數(shù)應(yīng)用場景空免,我們不需要自己去創(chuàng)建ApplicationContext的實(shí)例空另。例如在web應(yīng)用中,只需要在web.xml中增加8行配置就可以了:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Figure 1. The Spring IoC container

IoC容器的作用

Configuration metadata

元數(shù)據(jù)的三種配置方式:

  • 完全XML
  • 少量XML(component-scan) + Java注解
  • Java代碼(全部使用注解)

1 spring-core 包結(jié)構(gòu)

<pre>
src
└─org
└─springframework
├─asm
├─cglib
│ └─core
├─core
│ ├─annotation
│ ├─codec
│ ├─convert
│ │ ├─converter
│ │ └─support
│ ├─env
│ ├─io
│ │ ├─buffer
│ │ └─support
│ ├─serializer
│ │ └─support
│ ├─style
│ ├─task
│ │ └─support
│ └─type
│ ├─classreading
│ └─filter
├─lang
├─objenesis
└─util
├─backoff
├─comparator
├─concurrent
└─xml
</pre>

1.1 spring-core各模塊功能說明

1.asm Spring將ASM代碼重新打包蹋砚,提供ASM依賴扼菠。
http://blog.csdn.net/whos2002110/article/details/40817939
2.cglib cglib生成的動(dòng)態(tài)代理類命名規(guī)則(className$$classNameBySpringCGLIB$$hashCode)
3.core
4.lang 條件編譯注解
5.objenesis 對象實(shí)例化工具,封裝后提供緩存功能(單例)
6.util 各種工具類

2 spring-core.core

<pre>
core
├─annotation
├─codec
├─convert
│ ├─converter
│ └─support
├─env
├─io
│ ├─buffer
│ └─support
├─serializer
│ └─support
├─style
├─task
│ └─support
└─type
├─classreading
└─filter
</pre>
2.1 annotation


注解解析器和工具類

AnnotationUtils.getAnnotationAttributes(Annotation)  
AnnotationUtils.getValue(Annotation annotation, String attributeName)  

2.2 codec

各種編碼解碼工具
2.3 convert


轉(zhuǎn)碼工具

2.4 env##

2.4.1 概述####

env包是Spring3.1開始提供的新的屬性管理API坝咐,提供配置讀取和環(huán)境劃分能力娇豫,主要接口:PropertySource和Environment

2.4.2 PropertySource####

PropertySource.png

PropertySource:屬性源,key-value屬性對抽象畅厢,比如用于配置數(shù)據(jù)
PropertyResolver:屬性解析器冯痢,用于解析相應(yīng)key的value

2.4.2.1主要實(shí)現(xiàn)類#####

MapPropertySource:屬性來自于一個(gè)Map
ResourcePropertySource:屬性來自于一個(gè)properties文件
ServletContextPropertySource:屬性來自ServletContext上下文初始化參數(shù)
CompositePropertySource:提供了組合PropertySource的功能,查找順序就是注冊順序。

2.4.3 Environment####

environment類圖.png

Environment:環(huán)境浦楣,本身是一個(gè)PropertyResolver袖肥,但是提供了Profile特性,即可以根據(jù)環(huán)境得到相應(yīng)數(shù)據(jù)(即激活不同的Profile振劳,可以得到不同的屬性數(shù)據(jù)椎组,比如用于多環(huán)境場景的配置(正式機(jī)、測試機(jī)历恐、開發(fā)機(jī)DataSource配置))
Profile:剖面寸癌,Environment使Spring具有了剖面特性,只有激活的剖面的組件/配置才會(huì)注冊到Spring容器弱贼,類似于maven中profile蒸苇。這是context包中的一個(gè)注解。另外context包中還有一個(gè)叫做EnviromentAware的類吮旅,ApplicationContext是其子類溪烤,因此我們在SpringContext中可以獲取所有的配置和Profile信息。

@Inject Environment environment;
environment.getProperty( AppConfig.SERVER_HOST ),
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
    if (logger.isInfoEnabled()) {
        logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                "] not matching: " + getReaderContext().getResource());
    }
    return;
}

2.5 io##

2.5.1 概述####

在日常程序開發(fā)中庇勃,處理外部資源是很繁瑣的事情檬嘀,我們可能需要處理URL資源、File資源資源责嚷、ClassPath相關(guān)資源鸳兽、服務(wù)器相關(guān)資源(JBoss AS 5.x上的VFS資源)等等很多資源。因此處理這些資源需要使用不同的接口罕拂,這就增加了我們系統(tǒng)的復(fù)雜性揍异;而且處理這些資源步驟都是類似的(打開資源、讀取資源聂受、關(guān)閉資源)蒿秦,因此如果能抽象出一個(gè)統(tǒng)一的接口來對這些底層資源進(jìn)行統(tǒng)一訪問,是不是很方便蛋济,而且使我們系統(tǒng)更加簡潔棍鳖,都是對不同的底層資源使用同一個(gè)接口進(jìn)行訪問。
  spring提供一個(gè)Resource接口來統(tǒng)一這些底層資源一致的訪問碗旅,而且提供了一些便利的接口渡处,從而能提供我們的生產(chǎn)力。

2.5.2 Resource接口####

Spring的Resource接口代表底層外部資源祟辟,對JDK InputStream的擴(kuò)展医瘫,提供了對底層外部資源的一致性訪問接口。

2.5.3 主要實(shí)現(xiàn)類####

2.5.3.1 ByteArrayResource#####

ByteArrayResource代表byte[]數(shù)組資源旧困,對于“getInputStream”操作將返回一個(gè)ByteArrayInputStream醇份。ByteArrayResource可多次讀取數(shù)組資源稼锅,即isOpen ()永遠(yuǎn)返回false。

2.5.3.2 InputStreamResource#####

InputStreamResource代表java.io.InputStream字節(jié)流僚纷,對于“getInputStream ”操作將直接返回該字節(jié)流矩距,因此只能讀取一次該字節(jié)流,即“isOpen”永遠(yuǎn)返回true怖竭。

2.5.3.4 FileSystemResource

FileSystemResource代表java.io.File資源锥债,對于“getInputStream ”操作將返回底層文件的字節(jié)流,“isOpen”將永遠(yuǎn)返回false痊臭,從而表示可多次讀取底層文件的字節(jié)流哮肚。

2.5.3.5 ClassPathResource

ClassPathResource代表classpath路徑的資源,將使用ClassLoader進(jìn)行加載資源广匙。classpath 資源存在于類路徑中的文件系統(tǒng)中或jar包里允趟,且“isOpen”永遠(yuǎn)返回false,表示可多次讀取資源艇潭。
ClassPathResource加載資源替代了Class類和ClassLoader類的“getResource(String name)”和“getResourceAsStream(String name)”兩個(gè)加載類路徑資源方法拼窥,提供一致的訪問方式戏蔑。
ClassPathResource提供了三個(gè)構(gòu)造器:
public ClassPathResource(String path):使用默認(rèn)的ClassLoader加載“path”類路徑資源蹋凝;
public ClassPathResource(String path, ClassLoader classLoader):使用指定的ClassLoader加載“path”類路徑資源;
比如當(dāng)前類路徑是“cn.javass.spring.chapter4.ResourceTest”总棵,而需要加載的資源路徑是“cn/javass/spring/chapter4/test1.properties”鳍寂,則將加載的資源在“cn/javass/spring/chapter4/test1.properties”;
public ClassPathResource(String path, Class<?> clazz):使用指定的類加載“path”類路徑資源情龄,將加載相對于當(dāng)前類的路徑的資源迄汛;

2.5.3.6 UrlResource#####

UrlResource代表URL資源,用于簡化URL資源訪問骤视“鞍“isOpen”永遠(yuǎn)返回false,表示可多次讀取資源专酗。
UrlResource一般支持如下資源訪問:
http:通過標(biāo)準(zhǔn)的http協(xié)議訪問web資源睹逃,如new UrlResource(“http://地址”);
ftp:通過ftp協(xié)議訪問資源祷肯,如new UrlResource(“ftp://地址”)沉填;
file:通過file協(xié)議訪問本地文件系統(tǒng)資源,如new UrlResource(“file:d:/test.txt”)佑笋;

2.5.3.7 ServletContextResource#####

ServletContextResource代表web應(yīng)用資源翼闹,用于簡化servlet容器的ServletContext接口的getResource操作和getResourceAsStream操作;

2.5.4 ResourceLoader接口####

public interface ResourceLoader {  
       Resource getResource(String location);  
       ClassLoader getClassLoader();  
}  

getResource接口用于根據(jù)提供的location參數(shù)返回相應(yīng)的Resource對象蒋纬;而getClassLoader則返回加載這些Resource的ClassLoader猎荠。

Spring提供了一個(gè)適用于所有環(huán)境的DefaultResourceLoader實(shí)現(xiàn)坚弱,可以返回ClassPathResource、UrlResource关摇;還提供一個(gè)用于web環(huán)境的ServletContextResourceLoader史汗,它繼承了DefaultResourceLoader的所有功能,又額外提供了獲取ServletContextResource的支持拒垃。

ResourceLoader在進(jìn)行加載資源時(shí)需要使用前綴來指定需要加載:“classpath:path”表示返回ClasspathResource停撞,“http://path”和“file:path”表示返回UrlResource資源,如果不加前綴則需要根據(jù)當(dāng)前上下文來決定悼瓮,DefaultResourceLoader默認(rèn)實(shí)現(xiàn)可以加載classpath資源戈毒。

2.6 serializer##

序列化和反序列化

public interface Serializer<T> {
    void serialize(T object, OutputStream outputStream) throws IOException;
}
public interface Deserializer<T> {
    T deserialize(InputStream inputStream) throws IOException;
}

2.7 style

格式化輸出工具類
···
public interface ValueStyler {
String style(Object value);
}
public interface ToStringStyler {
void styleStart(StringBuilder buffer, Object obj);
void styleEnd(StringBuilder buffer, Object obj);
void styleField(StringBuilder buffer, String fieldName, Object value);
void styleValue(StringBuilder buffer, Object value);
void styleFieldSeparator(StringBuilder buffer);
}
···

2.8 task

2.8.1 概述####

Java SE 5.0引入了ThreadPoolExecutor、ScheduledThreadPoolExecutor横堡。Spring 2.x借助ConcurrentTaskExecutor和ThreadPoolTaskExecutor能夠通過IoC配置形式自定義它們暴露的各個(gè)屬性埋市。
TaskExecutor接口,是對java.util.concurrent.Executor接口的擴(kuò)展命贴。給其他組件提供線程池的抽象道宅。
例如ApplicationEventMulticaster組件、JMS的AbstractMessageListenerContainer和對Quartz的整合都使用了TaskExecutor抽象來提供線程池胸蛛。

task.png

2.8.2 配置與使用####

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <!-- 核心線程數(shù) -->     
    <property name="corePoolSize" value="5" />
    <!-- 最大線程數(shù) -->  
    <property name="maxPoolSize" value="50" />
    <!-- 隊(duì)列最大長度 -->
    <property name="queueCapacity" value="1000" />
    <!-- 線程池維護(hù)線程所允許的空閑時(shí)間污茵,默認(rèn)為60s -->
    <property name="keepAliveSeconds" value="60" />
</bean>
@Resource(name = "taskExecutor")
private TaskExecutor taskExecutor;
taskExecutor.execute(()-> {
    ...
});

2.8.3 實(shí)現(xiàn)類

從類圖上很明顯可以看出分為同步Executor和異步Executor。同步比較簡單葬项,就是調(diào)用一下的run方法泞当。下面主要分析異步。

  • SimpleAsyncTaskExecutor:每次調(diào)用都啟動(dòng)一個(gè)新線程民珍。但是襟士,它還是支持對并發(fā)總數(shù)設(shè)限,當(dāng)超過線程并發(fā)總數(shù)限制時(shí)嚷量,阻塞新的調(diào)用陋桂,直到有位置被釋放。
  • ConcurrentTaskExecutor:對Java 5 java.util.concurrent.Executor類的適配蝶溶,暴露了Executor的配置參數(shù)作為bean屬性嗜历,可以配置自己的Executor,可以設(shè)置任務(wù)裝飾器身坐。
  • **ThreadPoolTaskExecutor **:對java.util.concurrent.ThreadPoolExecutor的包裝秸脱。
  • ThreadPoolTaskScheduler:對java.util.concurrent.ScheduledExecutorService的封裝,并提供了@Scheduled 注解,極大簡化了ScheduledExecutorService的操作部蛇。
    使用方法:
// 修改spring context配置文件摊唇,增加xmlns和xsi
// xmlns
xmlns:task="http://www.springframework.org/schema/task"
// xsi
http://www.springframework.org/schema/task  
http://www.springframework.org/schema/task/spring-task-3.1.xsd  
//增加task注解掃描
<task:annotation-driven/>  
// 方法上加Scheduled 注解,支持fixedDelay涯鲁、Cron等多種方式
@Scheduled(cron="0/3 * *  * * ? ")   //每3秒執(zhí)行一次  
public void foo(){  
    ...  
} 

3.Spring-Core.utils#

<pre>
util
├─backoff
├─comparator
├─concurrent
└─xml
</pre>

3.1 backoff##

backoff.png

Spring封裝的退避算法巷查,用于獲取重試間隔有序。兩個(gè)實(shí)現(xiàn)類,F(xiàn)ixedBackOff是按照固定時(shí)間間隔重試岛请,ExponentialBackOff是間隔以指數(shù)方式增長旭寿。

3.2 concurrent##

Spring中對java.util.concurrent.Future的擴(kuò)展,支持Future適配崇败,F(xiàn)utureTask添加多個(gè)回調(diào)函數(shù)盅称。

20141119213430375.jpg

3.2.1 主要類

ListenableFuture<T>:增加擴(kuò)展功能使用addCallback()方法支持增加回調(diào)函數(shù)
ListenableFutureTask<T>:FutureTask子類,主要是為了增加回調(diào)函數(shù)注冊和回調(diào)函數(shù)調(diào)用功能后室。該類重寫了done()方法缩膝,執(zhí)行對回調(diào)函數(shù)隊(duì)列的調(diào)用。

3.2.2 應(yīng)用####

這個(gè)工具類應(yīng)用在Spring4.1的異步新特性中岸霹。Spring4.1提供了@Asyc注解疾层,被注解的類或方法將擁有異步處理能力

  • 相關(guān)的配置:
    <task:annotation-driven />指定@Async使用的線程池
    <task:executor />配置線程池參數(shù)

3.3 各種工具類##

ClassUtils:Class類工具,提供操作class類的方法贡避。
比如:獲知類痛黎、方法上是否有注解,獲取類注解刮吧,獲取某package下所有class等湖饱。提供class緩存
CollectionUtils:集合工具類,提供集合的轉(zhuǎn)換、查找皇筛、判空等方法琉历。
DigestUtils:對java.serurity.MessageDigest的封裝坠七,提供單向加密方法水醋。
ReflectionUtils:反射工具類,提供各種反射操作彪置,并包裝了反射過程中可能出現(xiàn)的異常拄踪。
SystemPropertyUtils:placeholder解析工具類。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拳魁,一起剝皮案震驚了整個(gè)濱河市惶桐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌潘懊,老刑警劉巖姚糊,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異授舟,居然都是意外死亡救恨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門释树,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肠槽,“玉大人擎淤,你說我怎么就攤上這事〗障桑” “怎么了嘴拢?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寂纪。 經(jīng)常有香客問我席吴,道長,這世上最難降的妖魔是什么捞蛋? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任抢腐,我火速辦了婚禮,結(jié)果婚禮上襟交,老公的妹妹穿的比我還像新娘迈倍。我一直安慰自己,他們只是感情好捣域,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布啼染。 她就那樣靜靜地躺著,像睡著了一般焕梅。 火紅的嫁衣襯著肌膚如雪迹鹅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天贞言,我揣著相機(jī)與錄音斜棚,去河邊找鬼。 笑死该窗,一個(gè)胖子當(dāng)著我的面吹牛弟蚀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播酗失,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼义钉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了规肴?” 一聲冷哼從身側(cè)響起捶闸,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拖刃,沒想到半個(gè)月后删壮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡兑牡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年央碟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片发绢。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硬耍,死狀恐怖垄琐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情经柴,我是刑警寧澤狸窘,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站坯认,受9級(jí)特大地震影響翻擒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜牛哺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一陋气、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧引润,春花似錦巩趁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至奴曙,卻和暖如春别凹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背洽糟。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工炉菲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蕴侧,地道東北人墓赴。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像赚哗,于是被迫代替她去往敵國和親浇雹。 傳聞我的和親對象是個(gè)殘疾皇子沉御,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)昭灵,斷路器,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評論 6 342
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,527評論 25 707
  • 出走的貓咪 流浪的狗 幸福是自由 在霓虹路口 要不要留伐谈,該不該走 我站在你家門口 戀人的眼神烂完,醉人的酒 喜悅是眼淚...
    俞米閱讀 272評論 0 5
  • 每天明白一個(gè)道理,每天習(xí)得一句英文诵棵! 溫柔暴擊立德金句抠蚣,等你一起讀~ 2017.11.15立德金句中英文: The...
    瞳小甜Rosie閱讀 204評論 0 0