核心两个类: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);
}
}