spring 二:自己创建一个简易版spring

在这里简单的实现一下spring容器对对象的的存入和取出

首先要下载几个必备的jar包,地址如下:

    <dependency>
	  <groupId>org.springframework</groupId>
	  <artifactId>spring-context</artifactId>
	  <version>5.0.8.RELEASE</version>
	</dependency>
    
    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>
    
     <dependency>
      <groupId>jaxen</groupId>
      <artifactId>jaxen</artifactId>
      <version>1.1.1</version>
    </dependency>

建立一个Factory的接口对应的是spring中的BeanFactory接口

package spring;

public interface BeanFactoryDemo {
	Object getBean(String objName);                //对应的是BeanFactory中从容器获取对象的方法,其有三种重载方式
	<T> T getBean(String objName,Class<T> type);
	<T> T getBean(Class<T> type);
}

Factory的实现类即对应spring中根据xml创建对象并为对象赋值和获取对象的类:

package spring;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.table.DefaultTableColumnModel;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ClassPathXMLApplicationContextDemo implements BeanFactoryDemo{
	private static final String DEFULT_XML_NAME="demo.xml";
	private String xmlName;
	private Map<String,Node> map=new HashMap<>();		
	//这个map即代表spring容器,键值为对象名,值的值为内部类Node的对象,Node包含了这个对象及其这个对象在xml中对应的节点,因为map的键值唯一,所以也间接实现了单例
	
	/*
	 * 加载配置文件
	 */
	
	public ClassPathXMLApplicationContextDemo(String xmlName) throws Exception  {	//构造器
		this.xmlName=xmlName;														//当有参数时,将xml设置为指定xml
		loader();
	}
	
	public ClassPathXMLApplicationContextDemo() throws Exception {					//构造器
		this.xmlName=DEFULT_XML_NAME;												//设置xml为默认xml文件
		loader();
	}

	public void loader() throws Exception{											//实现底层的一些处理,并创建xml中的所有对象并将其放入map
		//获取一个xml的输入流
		InputStream in=ClassPathXMLApplicationContextDemo.class.getClassLoader().getResourceAsStream(xmlName);
		SAXReader reader=new SAXReader();											//新建一个reader对象
		Document doc=reader.read(in);												//创建一个文档对象  使用reader读取流中的内容
		Element root=doc.getRootElement();											//获取根结点
		List<Element> childrens=root.elements();									//获取根结点的子节点即所有的对象节点
		
		for (Element e : childrens) {												//遍历所有xml中对象的节点
			String objName=e.attributeValue("id");									//获取对象点的id属性的值
			String classPath=e.attributeValue("class");								//获取class属性值
			
			Class c=Class.forName(classPath);										//利用反射得到类
			Object obj=c.newInstance();												//通过反射创建对象
			
			Node node=new Node(obj,e);												//将新建的对象和其在xml中对应的节点一起封装成一个Node对象
			map.put(objName,node);													//将生成的Node对象放入spring容器,以待使用
			
			setAttributes();														//调用赋值函数,为容器中的对象赋值
			
		}	
	}
	
	private void setAttributes() throws Exception{									//给对象赋值
		Collection<Node> list=map.values();											//获取到map中的所有值的值放入一个Node类型的list
		for (Node node : list) {													//遍历值的list
			Object obj=node.getObj();												//获取到真正的对象,准备为其赋值
			Element e=node.getE();													//获取到对象在xml中对应的节点
			Class c=obj.getClass();													//根据对象获取对象的类型
			List<Element> echildrens=e.elements();									//获取对象节点的所有子节点,即为属性赋值的节点,并将其放入一个list
			if(echildrens.size()>0) {												//判断list是否为空
				for (Element ec : echildrens) {										//遍历bean的子节点(),即赋值节点
					String attributeName=ec.attributeValue("name");					//获取此属性的值,对应的是封装类中的属性名称
					String attributeValue=ec.attributeValue("value");
					String attributeRef=ec.attributeValue("ref");
					//获取set方法
					String methodName="set"+attributeName.substring(0, 1).toUpperCase()+attributeName.substring(1)  ;
					Field field=c.getDeclaredField(attributeName);
					Class fieldType=field.getType();
					Method method=c.getMethod(methodName, new Class[] {fieldType});
					if(attributeValue!=null) {
						method.invoke(obj, new Object[] {typeHandler(attributeValue,fieldType)});//执行获取到的set方法,在传参时调用了类型处理器
					}else if(attributeRef!=null) {
						Object refObj=map.get(attributeRef).getObj();
						method.invoke(obj, new Object[] {refObj});
					}	
				}
			}
		}
	}
	private Object typeHandler(String value,Class t) {								//类型处理器
		Object obj=null;
		String n1=t.getName();
		if(n1.equals(Integer.class.getName())) {
			obj=Integer.parseInt(value);
		}else if(n1.equals(Character.class.getName())) {
			obj=value.charAt(0);
		}else if(n1.equals(Double.class.getName())) {
			obj=Double.parseDouble(value);
		}else if(n1.equals(String.class.getName())) {
			obj=value;
		}
		return obj;
	}
	
	@Override
	public Object getBean(String objName) {											//从容器中获取对象
		Object obj=map.get(objName).getObj();
		return obj;
	}

	@Override
	public <T> T getBean(String objName, Class<T> type) {							//从容器中获取对象(重载)
		Object obj=map.get(objName).getObj();
		return (T)obj;
	}

	@Override
	public <T> T getBean(Class<T> type) {											//从容器中获取对象(重载)
		Object obj=null;
		String className=type.getName();											//得到完整类路径
		Collection<Node> list=map.values();
		for (Node obj1 : list) {
			if(obj1.getClass().getName().equals(className)) {
				obj=obj1.getObj();
			}
		}
		return (T)obj;
	}
	private class Node{																//内部类:将Object和类型进行封装
		private Object obj;
		private Element e;
		
		public Node(Object obj,Element e) {
			this.obj=obj;
			this.e=e;
		}

		public Object getObj() {
			return obj;
		}

		public void setObj(Object obj) {
			this.obj = obj;
		}

		public Element getE() {
			return e;
		}

		public void setE(Element e) {
			this.e = e;
		}
		
	}

}

现在就可以测试这个简易版本的spring了:

首先书写封装类:

package spring;

public class A {
	public String name;
	public Integer id;
	public A() {
		System.out.println("创建了A的对象!");
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	@Override
	public String toString() {
		return "A [name=" + name + ", id=" + id + "]";
	}
}
package spring;

public class B {
	public B() {
		System.out.println("创建了B的对象!");
	}
}
package spring;

public class C {
	private A a;
	private B b;
	public C() {
		System.out.println("创建了C的对象!");
	}
	public A getA() {
		return a;
	}
	public void setA(A a) {
		this.a = a;
	}
	public B getB() {
		return b;
	}
	public void setB(B b) {
		this.b = b;
	}
	@Override
	public String toString() {
		return "C [a=" + a + ", b=" + b + "]";
	}
	
}

书写xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="a1" class="spring.A" >
		<property name="id" value="111"></property>
		<property name="name" value="张三"></property>
	</bean>
	<bean id="b" class="spring.B" />
	<bean id="a2" class="spring.A" />
	<bean id="c" class="spring.C">
		<property name="a" ref="a1"></property>
		<property name="b" ref="b"></property>
	</bean>
</beans>

测试类的书写:

package spring;

public class Test {
	public static void main(String[] args){
		try {
			BeanFactoryDemo demo=new ClassPathXMLApplicationContextDemo("applicationContext.xml");
			System.out.println(demo.getBean("c"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

其输出结果为:

猜你喜欢

转载自blog.csdn.net/zuo_h_dr/article/details/85949015
今日推荐