几天使用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.youkuaiyun.com/detail/u010785969/7960093