模拟spring中的ClassPathXmlApplicationContext的实现

最近,看spring,觉得spring的一些源码,很牛就来模仿下,模仿的目的不是为了炫耀啥,只是提高自己的编码质量。

要模仿ClassPathXmlApplicationContext类的实现,首先要读取spring中applicationContext.xml的内容,同时还要生成类的实例,自然用到的技术就有 dom4j的操作、再就是java 的反射机制、路径操作。

为了测试我在applicationContext.xml中添加了一个bean。

1、applicationContext.xml文件的内容如下:

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
  5.  <bean id="person" class="com.cvicse.service.impl.PersonServiceImpl" />  
  6. </beans>  

 2、为了存取bean的信息,我们定义一个definebean的pojo类

Java代码 复制代码
  1. package com.cvicse.bean;   
  2.   
  3. /**  
  4.  *   
  5.  * @功能:存储bean的pojo类  
  6.  * @创建人 gao_jie  
  7.  * @创建日期 Jun 16, 2009  
  8.  * @版本 1.0  
  9.  *   
  10.  */  
  11. public class DefineBean {   
  12.   
  13.     private String id;   
  14.     private String className;   
  15.   
  16.     public DefineBean(String id, String className) {   
  17.         this.id = id;   
  18.         this.className = className;   
  19.     }   
  20.   
  21.     public String getId() {   
  22.         return id;   
  23.     }   
  24.   
  25.     public void setId(String id) {   
  26.         this.id = id;   
  27.     }   
  28.   
  29.     public String getClassName() {   
  30.         return className;   
  31.     }   
  32.   
  33.     public void setClassName(String className) {   
  34.         this.className = className;   
  35.     }   
  36. }  
package com.cvicse.bean;

/**
 * 
 * @功能:存储bean的pojo类
 * @创建人 gao_jie
 * @创建日期 Jun 16, 2009
 * @版本 1.0
 * 
 */
public class DefineBean {

	private String id;
	private String className;

	public DefineBean(String id, String className) {
		this.id = id;
		this.className = className;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}
}

 

3、实现ClassPathXmlApplicationContext类

Java代码 复制代码
  1. package com.cvicse.util;   
  2.   
  3. import java.net.URL;   
  4. import java.util.ArrayList;   
  5. import java.util.HashMap;   
  6. import java.util.List;   
  7. import java.util.Map;   
  8.   
  9. import org.dom4j.Document;   
  10. import org.dom4j.DocumentException;   
  11. import org.dom4j.Element;   
  12. import org.dom4j.XPath;   
  13. import org.dom4j.io.SAXReader;   
  14.   
  15. import com.cvicse.bean.DefineBean;   
  16.   
  17. /**  
  18.  *   
  19.  * @功能 ClassPathApplicationContext类  
  20.  * @创建人 gao_jie  
  21.  * @创建日期 Jun 16, 2009  
  22.  * @版本 1.0  
  23.  *   
  24.  */  
  25. public class ClassPathApplicationContext {   
  26.   
  27.     /**  
  28.      * 获取xml文件中的说有bean对应类  
  29.      */  
  30.     private List<DefineBean> beanslist = new ArrayList<DefineBean>();   
  31.   
  32.     /**  
  33.      * 存储各个实例的键值对  
  34.      */  
  35.     private Map<String, Object> sigletons = new HashMap<String, Object>();   
  36.   
  37.     /**  
  38.      * 构造函数  
  39.      *   
  40.      * @param fileName  
  41.      */  
  42.     public ClassPathApplicationContext(String fileName) {   
  43.         this.readXMLFile(fileName);   
  44.         this.instanceBeans();   
  45.     }   
  46.        
  47.     /**  
  48.      * 获取应用实例  
  49.      * @param beanid  
  50.      * @return  
  51.      */  
  52.     public Object getBean(String beanid){   
  53.         return sigletons.get(beanid);   
  54.     }   
  55.   
  56.     /**  
  57.      * 读取XMl文件  
  58.      *   
  59.      * @param fileName  
  60.      */  
  61.     @SuppressWarnings("unchecked")   
  62.     private void readXMLFile(String fileName) {   
  63.         // TODO Auto-generated method stub   
  64.         SAXReader reader = new SAXReader();   
  65.         Document document = null;   
  66.         try {   
  67.             <STRONG><SPAN style="COLOR: #ff0000">// 获取XML文件的路径   
  68.             URL xmlpath = this.getClass().getClassLoader()   
  69.                     .getResource(fileName);</SPAN></STRONG>   
  70.         <SPAN style="COLOR: #000080"><STRONG>   document = reader.read(xmlpath);   
  71.             Map<String, String> nsMap = new HashMap<String, String>();   
  72.             nsMap.put("ns""http://www.springframework.org/schema/beans");// 加入命名空间   
  73.             XPath xsub = document.createXPath("//ns:beans/ns:bean");// 创建beans/bean查询路径   
  74.             xsub.setNamespaceURIs(nsMap);// 设置命名空间   
  75.             List<Element> beans = xsub.selectNodes(document);// 获取文档下所有bean节点   
  76.             for (Element element : beans) {   
  77.                 String id = element.attributeValue("id");   
  78.                 String className = element.attributeValue("class");   
  79.                 DefineBean bean = new DefineBean(id, className);   
  80.                 beanslist.add(bean);   
  81.             }</STRONG></SPAN>   
  82.         } catch (DocumentException e) {   
  83.             // TODO Auto-generated catch block   
  84.             e.printStackTrace();   
  85.         }   
  86.     }   
  87.   
  88.     /**  
  89.      * 实例化所有的bean  
  90.      */  
  91.     private void instanceBeans() {   
  92.         // TODO Auto-generated method stub   
  93.         for (DefineBean Bean : beanslist) {   
  94.   
  95.             if (Bean.getClassName() != null  
  96.                     && !"".endsWith(Bean.getClassName().trim())) {   
  97.                 // 采用java的反射机制进行类的实力化   
  98.                 try {   
  99.                     <SPAN style="COLOR: #ff0000"><STRONG>sigletons.put(Bean.getId(), Class.forName(   
  100.                             Bean.getClassName()).newInstance());</STRONG></SPAN>   
  101.                 } catch (InstantiationException e) {   
  102.                     // TODO Auto-generated catch block   
  103.                     e.printStackTrace();   
  104.                 } catch (IllegalAccessException e) {   
  105.                     // TODO Auto-generated catch block   
  106.                     e.printStackTrace();   
  107.                 } catch (ClassNotFoundException e) {   
  108.                     // TODO Auto-generated catch block   
  109.                     e.printStackTrace();   
  110.                 }   
  111.             }   
  112.         }   
  113.     }   
  114. }  
package com.cvicse.util;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import com.cvicse.bean.DefineBean;

/**
 * 
 * @功能 ClassPathApplicationContext类
 * @创建人 gao_jie
 * @创建日期 Jun 16, 2009
 * @版本 1.0
 * 
 */
public class ClassPathApplicationContext {

	/**
	 * 获取xml文件中的说有bean对应类
	 */
	private List<DefineBean> beanslist = new ArrayList<DefineBean>();

	/**
	 * 存储各个实例的键值对
	 */
	private Map<String, Object> sigletons = new HashMap<String, Object>();

	/**
	 * 构造函数
	 * 
	 * @param fileName
	 */
	public ClassPathApplicationContext(String fileName) {
		this.readXMLFile(fileName);
		this.instanceBeans();
	}
	
	/**
	 * 获取应用实例
	 * @param beanid
	 * @return
	 */
	public Object getBean(String beanid){
		return sigletons.get(beanid);
	}

	/**
	 * 读取XMl文件
	 * 
	 * @param fileName
	 */
	@SuppressWarnings("unchecked")
	private void readXMLFile(String fileName) {
		// TODO Auto-generated method stub
		SAXReader reader = new SAXReader();
		Document document = null;
		try {
			// 获取XML文件的路径
			URL xmlpath = this.getClass().getClassLoader()
					.getResource(fileName);
			document = reader.read(xmlpath);
			Map<String, String> nsMap = new HashMap<String, String>();
			nsMap.put("ns", "http://www.springframework.org/schema/beans");// 加入命名空间
			XPath xsub = document.createXPath("//ns:beans/ns:bean");// 创建beans/bean查询路径
			xsub.setNamespaceURIs(nsMap);// 设置命名空间
			List<Element> beans = xsub.selectNodes(document);// 获取文档下所有bean节点
			for (Element element : beans) {
				String id = element.attributeValue("id");
				String className = element.attributeValue("class");
				DefineBean bean = new DefineBean(id, className);
				beanslist.add(bean);
			}
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 实例化所有的bean
	 */
	private void instanceBeans() {
		// TODO Auto-generated method stub
		for (DefineBean Bean : beanslist) {

			if (Bean.getClassName() != null
					&& !"".endsWith(Bean.getClassName().trim())) {
				// 采用java的反射机制进行类的实力化
				try {
					sigletons.put(Bean.getId(), Class.forName(
							Bean.getClassName()).newInstance());
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

 

4、PersonServiceImpl及PersonService接口

Java代码 复制代码
  1. package com.cvicse.service.impl;   
  2.   
  3. import com.cvicse.service.PersonService;   
  4.   
  5. /**  
  6.  *   
  7.  * @功能 :测试类的实现    
  8.  * @创建人   gao_jie  
  9.  * @创建日期 Jun 16, 2009  
  10.  * @版本     1.0  
  11.  *   
  12.  */  
  13. public class PersonServiceImpl implements PersonService {   
  14.        
  15.     /* (non-Javadoc)  
  16.      * @see com.cvicse.service.impl.PersonService#save()  
  17.      */  
  18.     public void save(){   
  19.         System.out.println("我调用了Save方法!");   
  20.     }   
  21. }  
package com.cvicse.service.impl;

import com.cvicse.service.PersonService;

/**
 * 
 * @功能 :测试类的实现  
 * @创建人   gao_jie
 * @创建日期 Jun 16, 2009
 * @版本     1.0
 * 
 */
public class PersonServiceImpl implements PersonService {
	
	/* (non-Javadoc)
	 * @see com.cvicse.service.impl.PersonService#save()
	 */
	public void save(){
		System.out.println("我调用了Save方法!");
	}
}

 

Java代码 复制代码
  1. package com.cvicse.service;   
  2.   
  3. /**  
  4.  *   
  5.  * @功能 :测试类的接口      
  6.  * @创建人   gao_jie  
  7.  * @创建日期 Jun 16, 2009  
  8.  * @版本     1.0  
  9.  *   
  10.  */  
  11. public interface PersonService {   
  12.   
  13.     /**  
  14.      * 保存接口  
  15.      */  
  16.     public abstract void save();   
  17. }  
package com.cvicse.service;

/**
 * 
 * @功能 :测试类的接口    
 * @创建人   gao_jie
 * @创建日期 Jun 16, 2009
 * @版本     1.0
 * 
 */
public interface PersonService {

	/**
	 * 保存接口
	 */
	public abstract void save();
}

 5.测试类

Java代码 复制代码
  1. package com.cvicse.test;   
  2.   
  3. import com.cvicse.service.PersonService;   
  4. import com.cvicse.util.ClassPathApplicationContext;   
  5.   
  6. /**  
  7.  *   
  8.  * @功能;测试类  
  9.  * @创建人 gao_jie  
  10.  * @创建日期 Jun 16, 2009  
  11.  * @版本 1.0  
  12.  *   
  13.  */  
  14. public class Test {   
  15.   
  16.     /**  
  17.      * @param args  
  18.      */  
  19.     public static void main(String[] args) {   
  20.         // TODO Auto-generated method stub   
  21.         ClassPathApplicationContext xp = new ClassPathApplicationContext(   
  22.                 "applicationContext.xml");   
  23.         PersonService personService = (PersonService) xp.getBean("person");   
  24.         personService.save();   
  25.     }   
  26. }  
package com.cvicse.test;

import com.cvicse.service.PersonService;
import com.cvicse.util.ClassPathApplicationContext;

/**
 * 
 * @功能;测试类
 * @创建人 gao_jie
 * @创建日期 Jun 16, 2009
 * @版本 1.0
 * 
 */
public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ClassPathApplicationContext xp = new ClassPathApplicationContext(
				"applicationContext.xml");
		PersonService personService = (PersonService) xp.getBean("person");
		personService.save();
	}
}

 通过简单的测试可以输出: 

 我调用了Save方法!

呵呵,目的提高自己的编码质量,模拟也是一种进步!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值