使用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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念
xml文件介绍及使用
xml编程(一)-xml语法
XML文件结构和基本语法
第2章 包装类
XML入门的常见问题(二)
Java对象的强、软、弱和虚引用
JS解析XML文件和XML字符串详解
java中枚举的详细使用介绍
了解Xml格式
XML入门的常见问题(四)
深入SQLite多线程的使用总结详解
PlayFramework完整实现一个APP(一)
XML和YAML的使用方法
XML轻松学习总节篇