想要深入的熟悉了解Spring源碼,我覺得第一步就是要有一個能跑起來的極盡簡單的框架,下面我就教大家搭建一個最簡單的Spring框架,而且是基於Java Config形式的零配置Spring框架。
首先第一步創建一個空的maven web項目,這步很簡單,自行百度。
在maven項目的pom.xml文件中添加Spring基礎依賴:
<properties> <spring.version>4.3.7.RELEASE</spring.version> <slf4j.version>1.7.21</slf4j.version> <log4j.version>2.8.2</log4j.version> <logging.version>1.2</logging.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>${spring.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </dependency> <!-- log配置:Log4j2 + Slf4j --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-web --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-web</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <!-- 橋接:告訴Slf4j使用Log4j2 --> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <!-- 橋接:告訴commons logging使用Log4j2 --> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jcl</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies>
我推薦搭建基於Java Config形式的Spring框架,不需要配置文件,全部使用Java代碼形式來定義,簡潔明了,對於想要深入了解Spring源碼來說這點很重要,否則可能需要看非常多的Spring解析XML配置文件的解析類,對於任何人都不是很容易的功夫。而使用Java Config形式能直接看到配置類的運行流程,對了解Spring源碼很有幫助。
要搭建基於Java Config形式的Spring框架,要求Servlet-api版本3.0以上,同時推薦Spring版本4.0以上,日志可以使用我另一篇博客上的log4j2的配置,自己修改下輸出日志文件路徑就可以了。
public class WebContextInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] {RootContextConfig.class}; } } @Configuration @ComponentScan public class RootContextConfig { @Bean public Child child() { return new Child(); } } public class Child { } @Component public class Mother { }
把這幾個類都放在一個包下,然后啟動tomcat,應該就可以啟動Spring了,這就是一個最基本的Spring框架,而且包含了Java Config的Bean的定義以及組件掃描,RootContextConfig這個類就是容器的配置類,之后就可以開始跟着Spring框架的啟動流程看了,DEBUG跟着一步一步的走。
WebContextInitializer 的父類的將RootContextConfig 當做配置類生成一個AnnotationConfigWebApplicationContext
類型ApplicationContext容器,注入到ContextLoaderListener中。
...... protected WebApplicationContext createRootApplicationContext() { Class<?>[] configClasses = getRootConfigClasses(); if (!ObjectUtils.isEmpty(configClasses)) { AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext(); rootAppContext.register(configClasses); return rootAppContext; } else { return null; } } ...... protected void registerContextLoaderListener(ServletContext servletContext) { WebApplicationContext rootAppContext = createRootApplicationContext(); if (rootAppContext != null) { ContextLoaderListener listener = new ContextLoaderListener(rootAppContext); listener.setContextInitializers(getRootApplicationContextInitializers()); servletContext.addListener(listener); } else { logger.debug("No ContextLoaderListener registered, as " + "createRootApplicationContext() did not return an application context"); } }
不要對Tomcat內的源碼花時間,主要是看Spring的源碼,之后就可以看ContextLoaderListener的contextInitialized(…)方法了,Spring容器就是在這個方法里初始化生成的。如何初始化,這個太復雜了,需要花非常多的時間去看,去思考的,這里就不講了,不過我可以說一些我自己總結的小技巧:
說是看源碼,其實應該叫看和想。Spring源碼很復雜,我覺得花在思考上的時間至少要和看的時間對等。看了,如果沒有花時間想明白,等於白看。
理解重於記憶。Spring的流程很長,東西很多,如果單純靠記憶肯定記不過來的,知道每個組件的大體作用以及作用的節點就夠了,源碼就在那里,又不會跑,記不清了翻翻就看到了,多翻幾次就能夠慢慢記住了,最開始看的時候不要執着於記憶。
多做筆記。Spring組件很多,在最開始看的時候,推薦做些筆記,將每個重要接口的作用及關鍵代碼記錄下,有時間就看看,最先了解的組件是你切入Spring源碼的切口,借助他們能關聯到其他的組件。
多百度。在看一些關鍵接口或者類時,如果其代碼很復雜,先百度下吧,先對其功能有個了解,然后對照着功能看代碼會有很大的幫助。
要多遍地看,反復地看。別想着看一遍就能看明白,在最開始的幾次跟着初始化流程看源碼時,不要執着於某個細節。先對Spring所有的組件功能有個大體了解,對初始化流程有個大體的了解,這是深入的基礎。
多看日志,多DEBUG。多看日志能夠提高你對Spring流程的了解程度,而且在排錯時能有效提高效率;DEBUG是看源碼最好的一種方式,是解疑的最直接途徑,對於有些運行時難以觸及的代碼,需要你手動創造條件讓流程走入此處。
多總結,多動手。不要僅局限於看和思考,要動手。源碼看的仔細,基本能從源碼上看出很多Spring組件的使用方式,總結各種組件的使用方法,然后自己定義相應的組件,將其引入Spring中,查看其作用流程,這是你拓展Spring的第一步,既能增強對Spring的理解,也能提高你對Spring的拓展能力。
不斷完善框架。每熟悉一種組件的使用,就添加到自己的 框架中,不斷完善自己的框架,到最后你的框架能夠整合Spring大部分好用組件,也是你以后回顧Spring框架的最大助力。
多看注釋,看方法的名稱,參數和返回值。看注釋,理解類,屬性和方法的作用,着重第一段注釋;看方法的名稱,參數和返回值能對方法的作用有很明顯的說明。
以上就是我自己看Spring總結的一些小技巧,希望對你們有些助益。
后面持續更新相關文章,敬請期待!