几天使用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 原文链接:https://www.f2er.com/xml/297986.html