Java使用400行代码实现简单的Spring IOC容器(注意DOM4j工具类代码不做统计)

1、定义Bean结构封装类

/**  
* <p>Title: Bean.java</p>  
* <p>Description: </p>  
* <p>Copyright: Copyright (c) 2019</p>  
* <p>Company: www.nospring.com</p>  
* @author liu
* @date 2019年2月15日  
* @version 1.0  
*/  
package com.nospring.ioc;

import java.util.ArrayList;
import java.util.List;

/**
 * @author liuhaibing
 * @date 2019年2月15日  
 * @version 1.0  
 */
public class Bean {
	private String id;
	private String name;
	private String className;
	private String scope;
	private List<Property> propertyList = new ArrayList<Property>();
	
	public void addProperty(Property property) {
		propertyList.add(property);
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public String getScope() {
		return scope;
	}
	public void setScope(String scope) {
		this.scope = scope;
	}
	public List<Property> getPropertyList() {
		return propertyList;
	}
	public void setPropertyList(List<Property> propertyList) {
		this.propertyList = propertyList;
	}
}

2、定义bean属性结构封装类

/**  
* <p>Title: Property.java</p>  
* <p>Description: </p>  
* <p>Copyright: Copyright (c) 2019</p>  
* <p>Company: www.nospring.com</p>  
* @author liu
* @date 2019年2月15日  
* @version 1.0  
*/  
package com.nospring.ioc;

/**
 * @author liuhaibing
 * @date 2019年2月15日  
 * @version 1.0  
 */
public class Property {
	private String name;
	private String value;
	private String ref;
	private String type;
	
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public String getRef() {
		return ref;
	}
	public void setRef(String ref) {
		this.ref = ref;
	}
}

3、定义应用上下文类

/**  
* <p>Title: ApplicaitonContext.java</p>  
* <p>Description: </p>  
* <p>Copyright: Copyright (c) 2019</p>  
* <p>Company: www.nospring.com</p>  
* @author liu
* @date 2019年2月15日  
* @version 1.0  
*/  
package com.nospring.ioc;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;

import com.nospring.utils.DOMUtils;
/**
 * @author liuhaibing
 * @date 2019年2月15日  
 * @version 1.0  
 */
public class ApplicationContext {
	
	// 保存单例的对象
	private static Map<String, Object> sigletonObject = new HashMap<String, Object>();
	
	// 保存多例对象的初始化信息
	private static Map<String, Bean> prototypeObject = new HashMap<String, Bean>();
	
	/**
	 * @author liuhaibing
	 * @date 2019年2月15日  
	 * @version 1.0
	 */
	public ApplicationContext(String xmlFilePath) {
		// 通过DOM4j读取xml格式的配置文件
		Document document = DOMUtils.getXMLByInputStream(ApplicationContext.class.getClassLoader() 
				.getResourceAsStream(xmlFilePath));
		
		// 读取成功,解析配置文件
		if(null != document) {
			Element root = document.getRootElement();
			
			// 读取所有的bean节点
			List<Element> beanElements = (List<Element>) DOMUtils.getChildElement(root, "bean");
			
			// 遍历处理每个bean节点
			for(Element beanElement : beanElements) {
				String id = beanElement.attributeValue("id");
				String className = beanElement.attributeValue("class");
				String scope = beanElement.attributeValue("scope");
				
				System.out.println("--------");
				
				// scope默认是单例模式
				if(null == scope || scope.equals("sigleton")) {
					try {
						Class clazz = Class.forName(className);
						Object obj = clazz.newInstance();
						
						for(Object proElement : beanElement.elements("property")) {
							Element pElement = (Element)proElement;
							String pName = pElement.attributeValue("name");
							String value = pElement.attributeValue("value");
							String ref   = pElement.attributeValue("ref");
							String type   = pElement.attributeValue("type");
							Field field = clazz.getDeclaredField(pName);
							field.setAccessible(true);
							
							// 普通属性
							if(null == ref) {
								// 根据类型设置属性
								if(type.equals("java.lang.Integer")) {
									field.setInt(obj, Integer.parseInt(value));
								}else {
									// field.;
									field.set(obj, value);
								}
							}else { // 引用属性
								System.out.println("------id------" + id);
								// 通过ref的 value去查找bean
								field.set(obj, getBean(ref));
							}
						}
						
						sigletonObject.put(id, obj);
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}else { // 多例模式保存类的基本信息
					
					System.out.println("bean");
					
					Bean bean = new Bean();
					bean.setClassName(className);
					bean.setId(id);
					
					// 遍历保存属性信息
					for(Object proElement : beanElement.elements("property")) {
						Element pElement = (Element)proElement;
						String pName = pElement.attributeValue("name");
						String value = pElement.attributeValue("value");
						String ref   = pElement.attributeValue("ref");
						String type   = pElement.attributeValue("type");
						
						Property pro = new Property();
						pro.setName(pName);
						pro.setValue(value);
						pro.setRef(ref);
						pro.setType(type);
						
						// 将属性加入bean
						bean.addProperty(pro);
					}
					// 保存多例子模式的bean信息到HashMap
					prototypeObject.put(id, bean);
				} // 多例模式end
			}
		}
		
	}
	
	/**
	 * @author liuhaibing
	 * @date 2019年2月15日  
	 * @version 1.0
	 */
	public static Object getBean(String id) {
		
		Object obj = sigletonObject.get(id);
		
		// 如果在单例模式中查找到了bean,直接返回
		if(null != obj) {
			return obj;
		}
		
		Bean bean = prototypeObject.get(id);
		// 如果在多例子模式中找不到bean的配置信息,直接返回null
		if(null == bean) {
			return null;
		}else {
			try {
				// 加载类
				Class clazz = Class.forName(bean.getClassName());
				// 实例化类
				obj = clazz.newInstance();
				System.out.println(bean.getClassName());
				for(Property property : bean.getPropertyList()) {
					Field field = clazz.getDeclaredField(property.getName());
					field.setAccessible(true);
					
					System.out.println(property.getRef());
					
					if(null == property.getRef()) {
						// 根据类型设置属性
						if(property.getType().equals("java.lang.Integer")) {
							field.setInt(obj, Integer.parseInt(property.getValue()));
						}else {
							// field.;
							field.set(obj, property.getValue());
						}
					}else {
						System.out.println(id);
						System.out.println(getBean(property.getRef()));
						field.set(obj, getBean(property.getRef()));						
					}
				}
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return obj;
	}
	
	
}

4、辅助类dom4j

package com.nospring.utils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
 
/**
 * 基于dom4j的工具包
 *
 */
public class DOMUtils {
	
	/**
     * 通过输入流获取xml的document对象
     *
     * @param path    文件的路径
     * @return        返回文档对象
     */
    public static Document getXMLByInputStream(InputStream inputStream) {
        if (null == inputStream) {
            return null;
        }
        Document document = null;
        try {
            SAXReader reader = new SAXReader();
            document = reader.read(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return document;
    }
 
    /**
     * 通过文件的路径获取xml的document对象
     *
     * @param path    文件的路径
     * @return        返回文档对象
     */
    public static Document getXMLByFilePath(String path) {
        if (null == path) {
            return null;
        }
        Document document = null;
        try {
            SAXReader reader = new SAXReader();
            document = reader.read(new File(path));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return document;
    }
    
    /**
     * 通过xml字符获取document文档
     * @param xmlstr    要序列化的xml字符
     * @return            返回文档对象
     * @throws DocumentException
     */
    public static Document getXMLByString(String xmlstr) throws DocumentException{
        if(xmlstr==""||xmlstr==null){
            return null;
        }
        Document document = DocumentHelper.parseText(xmlstr);
        return document;
    }
 
    /**
     * 获取某个元素的所有的子节点
     * @param node    制定节点
     * @return        返回所有的子节点
     */
    public static List<Element> getChildElements(Element node) {
        if (null == node) {
            return null;
        }
        @SuppressWarnings("unchecked")
        List<Element> lists = node.elements();
        return lists;
    }
    
    /**
     * 获取指定节点的子节点
     * @param node            父节点
     * @param childnode        指定名称的子节点
     * @return                返回指定的子节点
     */
    public static List<Element> getChildElement(Element node,String childnode){
        if(null==node||null == childnode||"".equals(childnode)){
            return null;
        }
        return node.elements(childnode);
    }
    
    /**
     * 获取所有的属性值
     * @param node
     * @param arg
     * @return
     */
    public static Map<String, String> getAttributes(Element node,String...arg){
        if(node==null||arg.length==0){
            return null;
        }
        Map<String, String> attrMap = new HashMap<String,String>();
        for(String attr:arg){
            String attrValue = node.attributeValue(attr);
            attrMap.put(attr, attrValue);
        }
        return attrMap;
    }
    
    /**
     * 获取element的单个属性
     * @param node        需要获取属性的节点对象
     * @param attr        需要获取的属性值
     * @return            返回属性的值
     */
    public static String getAttribute(Element node,String attr){
        if(null == node||attr==null||"".equals(attr)){
            return "";
        }
        return node.attributeValue(attr);
    }
 
    /**
     * 添加孩子节点元素
     *
     * @param parent
     *            父节点
     * @param childName
     *            孩子节点名称
     * @param childValue
     *            孩子节点值
     * @return 新增节点
     */
    public static Element addChild(Element parent, String childName, String childValue) {
        Element child = parent.addElement(childName);// 添加节点元素
        child.setText(childValue == null ? "" : childValue); // 为元素设值
        return child;
    }
 
    /**
     * DOM4j的Document对象转为XML报文串
     *
     * @param document
     * @param charset
     * @return 经过解析后的xml字符串
     */
    public static String documentToString(Document document, String charset) {
        StringWriter stringWriter = new StringWriter();
        OutputFormat format = OutputFormat.createPrettyPrint();// 获得格式化输出流
        format.setEncoding(charset);// 设置字符集,默认为UTF-8
        XMLWriter xmlWriter = new XMLWriter(stringWriter, format);// 写文件流
        try {
            xmlWriter.write(document);
            xmlWriter.flush();
            xmlWriter.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return stringWriter.toString();
    }
 
    /**
     * 去掉声明头的(即<?xml...?>去掉)
     *
     * @param document
     * @param charset
     * @return
     */
    public static String documentToStringNoDeclaredHeader(Document document, String charset) {
        String xml = documentToString(document, charset);
        return xml.replaceFirst("\\s*<[^<>]+>\\s*", "");
    }
 
    /**
     * 解析XML为Document对象
     *
     * @param xml
     *            被解析的XMl
     * @return Document
     * @throws ParseMessageException
     */
    public final static Element parseXml(String xml) {
        StringReader sr = new StringReader(xml);
        SAXReader saxReader = new SAXReader();
        Document document = null;
        try {
            document = saxReader.read(sr);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        Element rootElement = document != null ? document.getRootElement() : null;
        return rootElement;
    }
 
    /**
     * 获取element对象的text的值
     *
     * @param e
     *            节点的对象
     * @param tag
     *            节点的tag
     * @return
     */
    public final static String getText(Element e, String tag) {
        Element _e = e.element(tag);
        if (_e != null)
            return _e.getText();
        else
            return null;
    }
 
    /**
     * 获取去除空格的字符串
     *
     * @param e
     * @param tag
     * @return
     */
    public final static String getTextTrim(Element e, String tag) {
        Element _e = e.element(tag);
        if (_e != null)
            return _e.getTextTrim();
        else
            return null;
    }
 
    /**
     * 获取节点值.节点必须不能为空,否则抛错
     *
     * @param parent    父节点
     * @param tag        想要获取的子节点
     * @return            返回子节点
     * @throws ParseMessageException
     */
    public final static String getTextTrimNotNull(Element parent, String tag) {
        Element e = parent.element(tag);
        if (e == null)
            throw new NullPointerException("节点为空");
        else
            return e.getTextTrim();
    }
 
    /**
     * 节点必须不能为空,否则抛错
     *
     * @param parent    父节点
     * @param tag        想要获取的子节点
     * @return            子节点
     * @throws ParseMessageException
     */
    public final static Element elementNotNull(Element parent, String tag) {
        Element e = parent.element(tag);
        if (e == null)
            throw new NullPointerException("节点为空");
        else
            return e;
    }
    
    /**
     * 将文档对象写入对应的文件中
     * @param document        文档对象
     * @param path            写入文档的路径
     * @throws IOException    
     */
    public final static void writeXMLToFile(Document document,String path) throws IOException{
        if(document==null||path==null){
            return;
        }
        XMLWriter writer = new XMLWriter(new FileWriter(path));
        writer.write(document);
        writer.close();
    }
    
}

##5. xml配置文件定义:

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="role" class="com.nospring.entity.Role" scope="prototype">
		<property name="roleId" value="1" type="java.lang.Integer"/>
		<property name="roleName" value="管理员" type="java.lang.String"/>
	</bean>
	<bean id="user" class="com.nospring.entity.User" scope="prototype">
		<property name="userName" value="Simon" type="java.lang.String"/>
		<property name="role" ref="role" />
	</bean>
</beans>
发布了34 篇原创文章 · 获赞 54 · 访问量 5031

猜你喜欢

转载自blog.csdn.net/nosprings/article/details/100120850
今日推荐