1.思路
通过xml配置bean,一个bean就是一个对象,bean中有property子标签,property代表要注入的属性。通过jdk原生解析xml获取数据,
通过反射创建对象,并把property的属性值注入给对象,实现自制IOC容器
2.实现步骤
1.实体类
User.java
@NoArgsConstructor
@Data
@ToString
public class User {
private int id;
private String name;
private int age;
public User(String name,int age){
this.name=name;
this.age=age;
}
}
Product.java
@NoArgsConstructor
@ToString
@Data
public class Product {
private String name;
private double price;
private int num;
}
2.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<factory>
<bean id="user" class="com.z.xml.User">
<property name="name" value="刃牙"></property>
<property name="age" value="24"></property>
<property name="phone" value="123456789"></property>
</bean>
<bean id="user1" class="com.z.xml.User">
<property name="name" value="皮可"></property>
<property name="age" value="24"></property>
<property name="phone" value="987654321"></property>
</bean>
<bean id="product" class="com.z.xml.Product">
<property name="name" value="iphone"></property>
<property name="price" value="16.5"></property>
<property name="num" value="1336"></property>
</bean>
</factory>
3.工厂类
Factory.java
public class Factory {
/**工厂存放对象的容器*/
private static Map<String, Object> map = new HashMap<>();
//程序启动自动创建对象
static {
try {
InputStream is = Factory.class.getClassLoader().getResourceAsStream("factory.xml");
createObject(is);
} catch (Exception e) {
e.printStackTrace();
}
}
/**读取文件创建对象*/
public static void createObject(InputStream is) throws Exception {
//1.获取工厂类对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//2.通过工厂类对象获取用于解析xml的对象
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
//3.解析xml
Document document = documentBuilder.parse(is);
//4.获取根节点
Element element = document.getDocumentElement();
//5.获取根节点的所有子节点
NodeList nodeList = element.getChildNodes();
//6.遍历所有子节点
for (int i = 0; i < nodeList.getLength(); i++) {
//7.对子节点进行操作
Node node = nodeList.item(i);
//如果为bean节点,进行如下操作
if (node.getNodeType() == Node.ELEMENT_NODE && ((Element)node).getTagName().equals("bean")) {
//接口向下转型
Element e = (Element) node;
//获取id
String key = e.getAttribute("id");
String value = e.getAttribute("class");
//获取id和class属性,利用全限定名class进行反射构建对象
Class cla = Class.forName(value);
Object object = cla.newInstance();
//读取bean节点下的子节点
NodeList cNodeList = e.getChildNodes();
for (int j = 0; j < cNodeList.getLength(); j++) {
Node cNode = cNodeList.item(j);
//读取bean节点下的property配置
if (cNode.getNodeType() == Node.ELEMENT_NODE && ((Element)cNode).getTagName().equals("property")) {
Element cE = (Element) cNode;
//获取property配置的属性名,和属性值,利用反射方法进行赋值
String cKey = cE.getAttribute("name");
String cValue = cE.getAttribute("value");
//确定属性类型,方便获取Method,这里用getDeclaredField破坏封装
Field field = cla.getDeclaredField(cKey);
Method method = cla.getMethod("set" + (char) ((int) cKey.charAt(0) - 32) + cKey.substring(1, cKey.length())
, field.getType());
//数据保护,不同类型数据赋值方式不一样
if (field.getType() == int.class) {
method.invoke(object, Integer.parseInt(cValue));
} else if (field.getType() == float.class) {
method.invoke(object, Float.parseFloat(cValue));
} else if (field.getType() == double.class) {
method.invoke(object, Double.parseDouble(cValue));
} else {
method.invoke(object, cValue);
}
}
}
map.put(key, object);
}
}
}
/**提供工厂的获取对象方法*/
public static Object getObject (String key){
return map.get(key);
}
}
4.测试
public class FactoryTest {
@Test
public void facotryTest(){
Object o1= Factory.getObject("user");
System.out.println(o1);
}
}