手写SpringIOC

核心两个类:BeanFactory 和 BeanDefinition

BeanFactory:

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * 简易版IOC 实现功能:加载xml 实现IOC、DI
 * 
 * @author Administrator
 *
 */
public class BeanFactory {
	// 用于存放beanDefinition的map
	private Map<String, Object> definitionMap;
	// 用于存放bean实例的map
	private Map<String, Object> beansMap;

	public BeanFactory(String iocXml) throws Exception {
		definitionMap = new HashMap<String, Object>();
		beansMap = new HashMap<String, Object>();
		// 获取配置文件全路径
		String location = this.getClass().getClassLoader().getResource(iocXml).getFile();
		loadBeans(location);
	}

	private void loadBeans(String location) throws Exception {
		// 配置文件流
		InputStream inputStream = new FileInputStream(location);
		// 得到BuilderFactory
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
		// 得到documentBuilder对象
		DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
		// 得到document
		Document document = documentBuilder.parse(inputStream);
		// 得到element
		Element element = document.getDocumentElement();
		NodeList beansNode = element.getElementsByTagName("bean");
		for (int i = 0; i < beansNode.getLength(); i++) {
			Element ele = (Element) beansNode.item(i);
			String id = ele.getAttribute("id");
			String className = ele.getAttribute("class");
			BeanDefinition beanDefinition = new BeanDefinition();
			beanDefinition.setId(id);
			beanDefinition.setClassName(className);
			// 属性注入
			NodeList propertiesNode = ele.getElementsByTagName("property");
			List<String> nameList = new ArrayList<String>();
			List<String> valueList = new ArrayList<String>();
			List<String> refList = new ArrayList<String>();
			for (int j = 0; j < propertiesNode.getLength(); j++) {
				Element elPro = (Element) propertiesNode.item(j);
				String name = elPro.getAttribute("name");
				String value = elPro.getAttribute("value");
				String ref = elPro.getAttribute("ref");
				nameList.add(name);
				valueList.add(value);
				refList.add(ref);
			}
			beanDefinition.setName(nameList);
			beanDefinition.setValue(valueList);
			beanDefinition.setRef(refList);
			// 注册
			definitionMap.put(id, beanDefinition);
		}
	}

	/**
	 * 获取bean 只有第一次使用bean的时候才会初始化bean
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	public Object getBean(String id) throws Exception {
		if (!beansMap.isEmpty() && beansMap.get(id) != null) {
			return beansMap.get(id);
		}
		Class<?> cl = null;
		Object newInstance = null;
		BeanDefinition definition = (BeanDefinition) definitionMap.get(id);
		if (definition.getId() != null && !definition.getId().equals("")) {
			String className = definition.getClassName();
			cl = Class.forName(className);
			newInstance = cl.newInstance();
			
			List<String> nameList = definition.getName();
			setBeanFields(cl, definition, newInstance, nameList);
			beansMap.put(id, newInstance);
		}
		return newInstance;
	}

	// 判断是否为数字
	private boolean isNumber(String value) {
		try {
			Integer.parseInt(value);
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	
	//设置属性
	private void setBeanFields(Class<?> cl, BeanDefinition definition , Object newInstance, List<String> nameList)throws Exception {
		for (int i = 0; i < nameList.size(); i++) {
			String name = nameList.get(i);
			Field declaredField = cl.getDeclaredField(name);
			declaredField.setAccessible(true);
			String value = definition.getValue().get(i);
			String ref = definition.getRef().get(i);
			if (value != null && !value.equals("")) {
				if (isNumber(value))
					declaredField.set(newInstance, Integer.parseInt(value));
				else
					declaredField.set(newInstance, value);
			} else {//如果是ref属性
				Object refObject = beansMap.get(ref);//获取该ref对应bean
				if(refObject == null) {
					BeanDefinition refDefinition = (BeanDefinition) definitionMap.get(ref);
					String refClassName = refDefinition.getClassName();
					Class<?> refForName = Class.forName(refClassName);
					Object refInstance = refForName.newInstance();
					List<String> refNameList = refDefinition.getName();
					setBeanFields(refForName, refDefinition, refInstance, refNameList);
					beansMap.put(ref, refInstance);
					declaredField.set(newInstance, refInstance);
				}else
					declaredField.set(newInstance, refObject);
			}
		}
	}
}

BeanDefinition:

import java.util.List;

public class BeanDefinition {
	private String id;
	private String className;
	private List<String> name;
	private List<String> value;
	private List<String> ref;

	public BeanDefinition() {
		// TODO Auto-generated constructor stub
	}

	public BeanDefinition(String id, String className, List<String> name, List<String> value, List<String> ref) {
		super();
		this.id = id;
		this.className = className;
		this.name = name;
		this.value = value;
		this.ref = ref;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public List<String> getName() {
		return name;
	}

	public void setName(List<String> name) {
		this.name = name;
	}

	public List<String> getValue() {
		return value;
	}

	public void setValue(List<String> value) {
		this.value = value;
	}

	public List<String> getRef() {
		return ref;
	}

	public void setRef(List<String> ref) {
		this.ref = ref;
	}

	@Override
	public String toString() {
		return "BeanDefinition [id=" + id + ", className=" + className + ", name=" + name + ", value=" + value
				+ ", ref=" + ref + "]";
	}

}

测试:

 XML:

<beans>
	<bean id="teacher" class="entities.Teacher">
		<property name="tId" value="1001"></property>
		<property name="name" value="张老师"></property>
	</bean>
	<bean id="student" class="entities.Student">
		<property name="sId" value="1002"></property>
		<property name="name" value="小明"></property>
		<property name="sex" value="男"></property>
	</bean>
</beans>

test:

class T {
	@Test
	void test() throws Exception {
		BeanFactory beanFactory = new BeanFactory("ioc.Xml");
		Teacher bean1 = (Teacher) beanFactory.getBean("teacher");
		Student bean2 = (Student) beanFactory.getBean("student");
		Student bean3 = (Student) beanFactory.getBean("student");
		System.out.println(bean1);
		System.out.println(bean2);
		System.out.println(bean2 == bean3);
	}
}
发布了50 篇原创文章 · 获赞 31 · 访问量 7351

猜你喜欢

转载自blog.csdn.net/qq_37685457/article/details/98853423