1. 程式人生 > >使用XPath解析xml實現簡單的Spring IOC完成bean的依賴注入

使用XPath解析xml實現簡單的Spring IOC完成bean的依賴注入

幾天使用Xpath解析xml檔案,例項化bean,完成spring IOC bean的依賴注入的簡單實現。

假設用如下格式的bean檔案:

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	
	<bean id="student" class="edu.hue.jk.bean.Student">
		<property name="stuName" value="xiao WeiJun"></property>
		<property name="stuDesc" value="a good student"></property>
		<property name="pen" ref="redPen"></property>
	</bean>
	<bean id="redPen" class="edu.hue.jk.bean.RedPen">
	</bean>
	<bean id="people" class="edu.hue.jk.bean.People">
		<property name="peopleName" value="XXX"></property>
	</bean>
</beans>
要完成bean的依賴注入,我們首先需要解析xml檔案,得到結點的class屬性值,然後通過反射呼叫來例項化bean ,將例項bean存入到map<String,Object>中。只是在解析的時候需要有一定的順序:

先初始化沒有property子節點的bean
初始化有property(屬性沒有ref)的bean
初始化有property(有ref)的bean
對應的解析檔案初始化類的程式碼實現:

package edu.hue.jk.xpath;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
/**
 * 使用xPath來解析xml 檔案 
 * 上下文環境,用來解析xml  並作bean的初始化工作
 */
public class MyApplicationContext {
	// 用來存放已經初始化過的bean
	private Map<String,Object> params;
	// 配置檔案的路徑
	private String filePath;
	// 建構函式
	public MyApplicationContext(String filePath) {
		super();
		this.filePath = filePath;
		params=new HashMap<String,Object>();
		initNoProperty();
		initPropertyNoRef();
		initPropertyRef();
	}
	// 解析檔案 根據xPath查詢得到結點集合
	public NodeList getNodeList(String path){
		NodeList result=null;
		try{
			XPathFactory xPathFactory=XPathFactory.newInstance();
			XPath xPath=xPathFactory.newXPath();
			InputSource inputSource=new InputSource(filePath);
			result=(NodeList)xPath.evaluate(path, inputSource, XPathConstants.NODESET);
		}
		catch(Exception e){
			System.out.println(e.getMessage());
		}
		return result;
	}
	//getBean方法
	public Object getBean(String beanId){
		return params.get(beanId);
	}
	
	
	/**************bean的初始化****************/
	// 首先初始化沒有property結點的bean
	void initNoProperty(){
		try{
			NodeList list=getNodeList("/beans/bean[not(child::property)]");
			for(int i=0;i<list.getLength();i++){
				Element element=(Element)list.item(i);
				//得到bean的Id
				String beanId=element.getAttribute("id");  
				//得到bean的class
				String beanClass=element.getAttribute("class");
				//根據反射建立bean的例項
				Object obj=Class.forName(beanClass).newInstance();
				//存放bean的例項
				params.put(beanId, obj);
			}
		}
		catch(Exception e){
			System.out.println(e.getMessage());
		}
	}
	// 然後初始化 有property但是沒有ref屬性的bean
	void initPropertyNoRef(){
		try{
			//找到所有沒有 ref屬性的property子節點 並且有property子節點的所有結點
			NodeList list=getNodeList("/beans/bean[not(child::property[@ref]) and child::property]");
			for(int i=0;i<list.getLength();i++){
				Element element=(Element)list.item(i);
				//得到bean的Id
				String beanId=element.getAttribute("id");  
				//得到bean的class
				String beanClass=element.getAttribute("class");
				//根據反射建立bean的例項
				Object obj=Class.forName(beanClass).newInstance();
				//得到所有的property子節點
				NodeList pList=getNodeList("/beans/bean[contains(@id,'"+beanId+"')]"+"/property");
				//遍歷子節點,注入屬性
				for(int j=0;j<pList.getLength();j++){
					//得到property結點
					Element pElement=(Element)pList.item(j);
					//得到屬性的名字
					String pName=pElement.getAttribute("name");
					//得到屬性的值
					String pValue=pElement.getAttribute("value");
					//構造方法名
					String methodName="set"+(""+pName.charAt(0)).toUpperCase()+pName.substring(1);
					//根據反射注入屬性
					Method method=Class.forName(beanClass).getMethod(methodName,String.class);
					method.invoke(obj, pValue);
				}
				//存放bean的例項
				params.put(beanId, obj);
			}
		}
		catch(Exception e){
			System.out.println(e.getMessage());
		}
	}
	//初始化有property子節點且property含有ref屬性的所有bean
	void initPropertyRef(){
		try{
			//找到所有有property子節點且property含有ref屬性的所有結點
			NodeList list=getNodeList("/beans/bean[child::property[@ref]]");
			for(int i=0;i<list.getLength();i++){
				Element element=(Element)list.item(i);
				//得到bean的Id
				String beanId=element.getAttribute("id");  
				//得到bean的class
				String beanClass=element.getAttribute("class");
				//根據反射建立bean的例項
				Object obj=Class.forName(beanClass).newInstance();
				//得到所有的property子節點
				NodeList pList=getNodeList("/beans/bean[contains(@id,'"+beanId+"')]"+"/property");
				//遍歷子節點,注入屬性
				for(int j=0;j<pList.getLength();j++){
					//得到property結點
					Element pElement=(Element)pList.item(j);
					//得到屬性的名字
					String pName=pElement.getAttribute("name");
					//得到屬性的值
					String pValue=pElement.getAttribute("value");
					//如果屬性依賴於另外的實體  則得到ref屬性
					String pref=pElement.getAttribute("ref");
					//構造方法名
					String methodName="set"+(""+pName.charAt(0)).toUpperCase()+pName.substring(1);
					//如果屬性值為空,則需要注入依賴屬性
					if(pValue==null|| "".equals(pValue)){
						Object target=params.get(pref);
						//System.out.println(target.getClass().getSimpleName());
						//根據反射注入屬性
						Method method=Class.forName(beanClass).getMethod(methodName,target.getClass());
						method.invoke(obj, target);
						
					}
					else{//如果屬性不為空則直接注入屬性
						//根據反射注入屬性
						Method method=Class.forName(beanClass).getMethod(methodName,String.class);
						method.invoke(obj, pValue);
					}
					
				}
				//存放bean的例項
				params.put(beanId, obj);
			}
		}
		catch(Exception e){
			System.out.println(e.getMessage());
		}
	}
}
最後測試程式:
package edu.hue.jk.test;

import edu.hue.jk.bean.People;
import edu.hue.jk.bean.RedPen;
import edu.hue.jk.bean.Student;
import edu.hue.jk.xpath.MyApplicationContext;

public class Test {

	public static void main(String[] args) {
		MyApplicationContext context=new MyApplicationContext("D:\\JavaWeb\\springMvcExercise\\XmlProject\\src\\testBeans.xml");
		Student stu=(Student)context.getBean("student");
		stu.usePen();
		
		RedPen rpen=(RedPen)context.getBean("redPen");
		rpen.showPen();
		
		People people=(People)context.getBean("people");
		people.showPeople();
	}

}
本程式的附件下載地址:http://download.csdn.net/detail/u010785969/7960093