IOC遵循是Spirng中对依赖倒转原则的原则,依赖倒转原则告诉我们:

  • 上层模块不应该依赖底层模块,他们都应该依赖于抽象
  • 抽象不应该依赖于细节,细节应该依赖于抽象

先读取bean的XML配置文件,然后使用beanId查找bean配置,并获取配置文件中class地址,得到地址后使用Java反射技术实例化对象,最后获取属性配置,使用反射技术进行赋值。
详细步骤:

  1. 利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象

  2. 对于Document对象获取根元素对象后对下面的标签进行遍历,判断是否有符合的id.
    如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象.

  3. 遍历标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理.

  4. 如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值.
    返回建立的对象,如果没有对应的id,或者下没有子标签都会返回null

    applicationContext.xml的文件定义:

1
2
3
4
5
6
7
8
9
10
11
12
<!--定义一个bean-->
<beans>
<bean id="user1" class = "com.wzl.ioc.User">
<property name ="userId" value = "0001"></property>
<property name = "userName" value="无知狼"></property>
</bean>

<bean id="user2" class = "com.wzl.ioc.User">
<property name ="userId" value = "0002"></property>
<property name = "userName" value="无知猫"></property>
</bean>
</beans>

代码的实现逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.wzl.ioc;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.util.StringUtils;

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


/**
* @ClassName ClassPathXmlApplicationContext
* @Description ClassPathXmlApplicationContext
* @Author wzl
* @Date 2020/11/12 16:14
*/
public class ClassPathXmlApplicationContext {

private String pathXml = null;

public ClassPathXmlApplicationContext(String pathXml) {
this.pathXml = pathXml;
}

public Object getBean(String beanId) throws Exception {
if (StringUtils.isEmpty(beanId)) {
throw new Exception("beanId is null");
}
SAXReader saxReader = new SAXReader();
Document read = saxReader.read(this.getClass().getClassLoader().getResource(pathXml));

Element rootElemement = read.getRootElement();
List<Element> elements = rootElemement.elements();
for (Element element : elements) {
String id = element.attributeValue("id");
if (StringUtils.isEmpty(id)) {
continue;
}
if (!id.equals(beanId)) {
continue;
}
// 使用java反射机制初始化对象
String beanClass = element.attributeValue("class");
Class<?> forName = Class.forName(beanClass);
Object newInstance = forName.newInstance();
List<Element> propertyElementList = element.elements();
for (Element el : propertyElementList) {
String name = el.attributeValue("name");
String value = el.attributeValue("value");
Field declaredField = forName.getDeclaredField(name);
declaredField.setAccessible(true);
declaredField.set(newInstance, value);
}
return newInstance;
}
return null;
}

public static void main(String[] args) {
ClassPathXmlApplicationContext classPath = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = null;
try {
user = (User) classPath.getBean("user2");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(user.getUserId() + user.getUserName());

}

}