本身動手寫spring容器(1)

     畢業剛剛一年多一點,畢業了後也順利的進入了一家著名的互聯網公司,作的是後臺系統,用的呢也是SSI(struts2,spring)框架,平時作作項目,也已足夠了,可是感受愈來愈沒動力了,愈來愈沒有激情了,就像咱們的老大說的,"每天接Task,有意思?,有時間不知道把框架的源碼看看!",最近加班相對較少,閒下來就來摸索一下spring。html

寫這篇文章只是想讓你們瞭解一下Spring究竟是怎麼運行的,並非想重造噢,但願你們看完這篇文章後能對Spring有更深刻的瞭解,對初學者有所幫助喔!好,言歸正傳,讓咱們來一塊兒探索吧!spring

 咱們先開看看spring是怎麼運行的。。編程

1  //讀取配置文件實例化一個IoC容器
2         ApplicationContext ctx=new ClassPathXmlApplicationContext("resources/beans.xml");
3          //從容器中獲取Bean,注意此處徹底「面向接口編程,而不是面向實現」
4          PersonService personService=(PersonService) ctx.getBean("personService",PersonService.class);
5          personService.sayHello();

咱們來分析一下,首先是加載spring的配置文件,此處是beans.xml框架

1     <bean id="personService" class="com.yangyang.service.impl.PersonServiceImpl">
2     </bean>

而後是經過調用getBean方法來獲取並實例化personService對象,最後是調用sayHello方法函數

 

那麼spring究竟是如何作到的呢?很明顯,第一步確定是要解析bean.xml文件,測試

爲此咱們寫一個本身的ClassPathXmlApplicationContext類來模擬spring的行爲,,此處加入一個參數爲string類型的構造函數,用來讀取配置文件及模擬spring之後的行爲,ui

 1 package com.juit;
 2 
 3 public class YhdClassPathXmlApplicationContext {
 4     /**
 5      * 構造方法,用來模擬spring的行爲
 6      * @param fileName
 7      */
 8     public YhdClassPathXmlApplicationContext(String fileName){
 9         this.readXml(fileName);
10     }
11     /**
12      * 根據文件名讀取xml的配置文件
13      * @param fileName
14      * Administer
15      * 2013-8-26 下午11:09:16
16      */
17     private void readXml(String fileName) {
18         // TODO Auto-generated method stub
19         
20     }
21 }

此處readxml啥都沒作,如今咱們來完成這個代碼,根據http://www.cnblogs.com/shunyang/p/3265100.html中提到的方式來解析xml文件,並將解析到的bean存到一個bean定義的類中,爲此咱們須要準備一個類BeanDefinition 用來存儲解析後xml文件。通過分析xml文件,可知比較簡單的配置通常有id,class(固然這裏爲了簡單隻用了兩個)等屬性,以下:this

固然咱們也須要加上一個全局的List的bean,用來存儲全部的beans,代碼見後面spa

 1 package com.juit;
 2 /**
 3  * Bean對象
 4  * @author Administer
 5  *
 6  */
 7 public class BeanDefinition {
 8     private String id;//bean的id
 9     private String className;//bean的類
10     public String getId() {
11         return id;
12     }
13     public void setId(String id) {
14         this.id = id;
15     }
16     public String getClassName() {
17         return className;
18     }
19     public void setClassName(String className) {
20         this.className = className;
21     }
22     public BeanDefinition(String id, String className) {
23         this.id = id;
24         this.className = className;
25     }
26 }

 

下面是解析xml文件的readXml方法:code

 1 private void readXml(String fileName) {
 2         //建立一個讀取器
 3         SAXReader saxReader=new SAXReader();
 4         Document document=null;
 5         try {
 6             //獲取要讀取的配置文件的路徑
 7             URL xmlPath=this.getClass().getClassLoader().getResource(fileName);
 8             //讀取文件內容
 9             document=saxReader.read(xmlPath);
10             //獲取xml中的根元素
11             Element rootElement=document.getRootElement();
12             for (Iterator iterator = rootElement.elementIterator(); iterator.hasNext();) {
13                 Element element = (Element) iterator.next();
14                 String id=element.attributeValue("id");//獲取bean的id屬性值
15                 String clazz=element.attributeValue("class");//獲取bean的class屬性值
16                 BeanDefinition beanDefinition=new BeanDefinition(id,clazz);
17 beanDefines.add(beanDefinition); 18 } 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 }

 解析完xml後,接下來就是bean的實例化,咱們在寫一個實例化bean的方法。

spring中是使用getBean的方式來獲取bean的,相似的能夠用Map的get取值來模擬,所以定義一個Map,用來存儲bean的id和bean的對應,完整的見下面

 
 1 public class YhdClassPathXmlApplicationContext{
 2     private List<BeanDefinition> beanDefines=new ArrayList<BeanDefinition>();//用來存儲全部的beans
 3     private Map<String, Object> sigletons =new HashMap<String, Object>();//用來存儲實例化後的bean
 4     /**
 5      * 構造方法,用來模擬spring的行爲
 6      * @param fileName
 7      */
 8     public YhdClassPathXmlApplicationContext1(String fileName){
 9         //1.讀取spring的配置文件
10         this.readXml(fileName);
11         //2.實例化bean
12         this.instanceBeans();
13     }
14     /**
15      * 完成實例化beans
16      * 
17      * Administer
18      * 2013-8-26 下午11:24:37
19      */
20     private void instanceBeans() {
21         // TODO Auto-generated method stub
22         
23     }
 
 

 

 

 而後咱們來完成instanceBeans方法

 1 /**
 2      * 完成實例化beans
 3      * 
 4      * Administer
 5      * 2013-8-18 上午1:07:51
 6      */
 7     private void instanceBeans() {
 8         if (beanDefines != null && beanDefines.size() >0) {
 9             //對每一個bean進行實例化
10             for (BeanDefinition beanDefinition : beanDefines) {
11                 try {
12                     //bean的class屬性存在的時候才進行實例化,不然不進行實例化
13                     if (beanDefinition.getClassName() != null && !beanDefinition.getClassName().equals("")) {
14                         //實例化的關鍵操做
15                         sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance());
16                         System.out.println("id爲:"+beanDefinition.getId()+"的bean實例化成功");
17                     }
18                 } catch (Exception e) {
19                     System.out.println("bean實例化失敗");
20                     e.printStackTrace();
21                 }
22             }
23         }
24     }

 實例化後咱們來寫一個getBean方法,用來在外部獲取實例化後的bean,這個搞個最簡單的根據bean的id來獲取

 1 /**
 2      * 經過bean名稱來獲取bean對象
 3      * @param beanName
 4      * @return
 5      * Administer
 6      * 2013-8-18 上午1:17:02
 7      */
 8     public Object getBean(String beanName){
 9         return sigletons.get(beanName);
10     }

這樣整個bean的實例化咱們已經作完了,是否是也不是很困難,固然咱們還缺乏一步,咱們須要測試咱們這個本身寫的這個spring是否是OK的,

 1 package com.juit;
 2 
 3 import org.junit.BeforeClass;
 4 import org.junit.Test;
 5 
 6 import com.juit.YhdClassPathXmlApplicationContext;
 7 import com.yangyang.service.PersonService;
 8 
 9 public class SpringTest {
10 
11     @BeforeClass
12     public static void setUpBeforeClass() throws Exception {
13     }
14 
15     @Test
16     public void testInstanceSping() {
17         YhdClassPathXmlApplicationContext ctx=new YhdClassPathXmlApplicationContext("resources/beans.xml");
18         PersonService personService=(PersonService)ctx.getBean("personService");
19 
20     }
21 
22 }

能夠看到控制檯打印着"

id爲:personService的bean實例化成功

終於大功告成了,固然這些只是我這個菜鳥的理解,歡迎各位大神的指導,接下來下篇將會實現spring的依賴注入。

相關文章
相關標籤/搜索