畢業剛剛一年多一點,畢業了後也順利的進入了一家著名的互聯網公司,作的是後臺系統,用的呢也是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的依賴注入。