學習Spring源碼的動機是一次偶然的單元測試, 以前對注入 ,控制反轉比較熟悉,先回顧一下當時測試 :java
目的:spring
測試SpringMvc項目中的model層(俗稱Service層) app
如下的例子均採用註解注入模式,沒有在spring.xml中定義bean .框架
UserModel的代碼:工具
package com.younchen.model; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service("personModel") public class PersonModel { @Autowired private Person person; public Person getPerson(){ return person; } public void setPerson(Person person) { this.person = person; } public void showPersonName(){ // System.out.println("姓名:"+person.getName()); } }
userModel( 能夠理解爲userService ) ,該model中注入了person實體, 因此不能在測試類中以 UserModel userModel = new UserModel() 的方式進行 showPersonName()方法的測試 (推薦mockito 測試框架), 注入須要spring 框架的支持,不然報空指針異常,因而Spring 容器上下文ApplicationContext登場了.單元測試
SpringUtil類:學習
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringUtil { private static ApplicationContext context = null; public static ApplicationContext getApplicationContext() { if (context == null) { context = new ClassPathXmlApplicationContext("spring.xml"); } return context; } public static ApplicationContext getApplicationContext(String path) { return new ClassPathXmlApplicationContext(path); } public static ApplicationContext getAnnotationConfigApplicationContext(String basePackages) { return new AnnotationConfigApplicationContext(basePackages); } }
這個工具類的做用是返回Spring上下文的實例,這樣一來能夠經過上下文獲取spring中配置的bean對象 .測試
先看一下person類:this
package com.younchen.model; import javax.inject.Named; @Named("person") public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Person類中的@Name的做用與spring配置文件中定義<bean name="preson" class="com.younchen.model.person"> 的做用是同樣的,前提是spring.xml中定義包掃描器spa
<context:component-scan base-package="com.younchen.*" />
如今看一下測試類:
package com.younchen.test; import com.younchen.model.PersonModel; import com.younchen.util.SpringUtil; public class ApplicationContext { public static void main(String[] args){ //獲取application Context PersonModel personModel = (PersonModel) SpringUtil.getApplicationContext().getBean("personModel"); personModel.getPerson().setName("黑貓"); personModel.showPersonName(); } }
運行結果:
2014-7-8 16:08:46 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@b749757: startup date [Tue Jul 08 16:08:46 CST 2014]; root of context hierarchy 2014-7-8 16:08:46 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring.xml] 2014-7-8 16:08:46 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init> 信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring 姓名:黑貓
依賴注入: 本例中的 Person 類, 不管是 在spring.xml中配置的方式,仍是用註解的方式,它都是由spring容器實例化的,不是人爲的去new 了一個對象。
控制反轉: 本例中不明顯, 主程序只是負責調用模塊的方法而不去管這個模塊的具體實現,常常以工廠模式出現。
依賴注入也是控制反轉的一種特殊形態,這裏舉個例子, 有些時候在userModel中注入的Person 能夠是Person的子類(這裏能夠參考一下 註解方式 同一個實體的不一樣註解方式 )而userModel的showPersonName方法無論Person的實例具體是哪一個類,只負責執行Person的getName方法.
由此對Spring源碼產生了興趣(待續)