手写spring ioc

原理

  • 容器:本质是一个map,核心功能 : 1.存对象(Bean)2.取对象 (按名称或类型获取Bean)3.管理依赖(自动注入所需Bean)
  • IOC: IoC(控制反转)就是把对象的创建和依赖管理交给容器,而不是在代码里手动 new 对象
  • DI:DI(依赖注入)是 IoC(控制反转)的实现方式,指的是由容器自动将对象的依赖注入进去,而不是手动创建。由容器来决定对象之间的依赖关系

步骤

  1. 解析xml
plaintext
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
public void parseXml() {  
SAXReader saxReader = new SAXReader();
InputStream is = this.getClass().getClassLoader().getResourceAsStream(xmlFile);
try {
Document document = saxReader.read(is);
// 获得根节点
Element rootElement = document.getRootElement();
//
List<Element> beans = rootElement.elements("bean");

classbeanMap = new HashMap<>();
for (Element element : beans) {
// 从Element中获取Classbean的属性
ClassBean classBean = new ClassBean();
String name = element.attributeValue("name");
String className = element.attributeValue("class");
List<Element> propertys = element.elements("property");
Map<String,Property> propertyMap = new HashMap<>();
// 将Element中的属性写入classBean中然后放入map
classBean.setName(name);
classBean.setClassName(className);
// 先赋予引用,再对引用对象修改
classBean.setPropertyMap(propertyMap);
classbeanMap.put(classBean.name, classBean);

for (Element element1 : propertys) {
String proName = element1.attributeValue("name");
String proValue = element1.attributeValue("value");
String proRef = element1.attributeValue("ref");
Property property = new Property();
property.setName(proName);
property.setValue(proValue);
property.setRef(proRef);
propertyMap.put(property.name, property);
}
}

} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
  1. 创建空的bean对象在容器中
    plaintext
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public void newBean() {  
    Set<Map.Entry<String, ClassBean>> entries = classbeanMap.entrySet();
    beanMap = new HashMap<>();
    for (Map.Entry<String, ClassBean> entry : entries) {
    ClassBean classBean = entry.getValue();
    String className = classBean.ClassName;
    String name = classBean.name;

    // 实例化对象
    try {
    Object o = Class.forName(className).getDeclaredConstructor().newInstance();
    beanMap.put(name, o);
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }
    }
  2. 依赖注入
    plaintext
    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
       public void dependencyInjection() {  
    Set<Map.Entry<String, ClassBean>> entries = classbeanMap.entrySet();
    for (Map.Entry<String, ClassBean> entry : entries) {
    //获取bean信息
    ClassBean classBean = entry.getValue();
    String name = classBean.getName();
    Map<String, Property> propertyMap = classBean.getPropertyMap();
    //获得空的bean对象
    Object o = beanMap.get(name);
    //将属性注入bean
    Set<Map.Entry<String, Property>> entries1 = propertyMap.entrySet();

    for (Map.Entry<String, Property> stringPropertyEntry : entries1) {
    //如果需要访问特定索引,先将entries1转为List
    Property property = stringPropertyEntry.getValue();
    String proName = property.getName();
    String proValue = property.getValue();
    String proRef = property.getRef();

    if (proRef != null) {
    // 获得需要引用的对象
    Object refBean = beanMap.get(proRef);
    try {
    // 反射动态获取 根据proName的不同,set名称也不同
    String SetMethod = "set" + proName.substring(0, 1).toUpperCase() + proName.substring(1);
    Method method = o.getClass().getMethod(SetMethod, refBean.getClass());
    method.invoke(o, refBean);

    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    } else if (proValue != null) {
    try {
    // 获得属性名
    Field valueField = o.getClass().getDeclaredField(proName);
    // 反射动态获取 根据proName的不同,set名称也不同
    String SetMethod = "set" + proName.substring(0, 1).toUpperCase() + proName.substring(1);
    Method method = o.getClass().getMethod(SetMethod, valueField.getType());
    // 判断属性类型,从而转换
    Class<?> valueFieldType = valueField.getType();
    if (valueFieldType == int.class || valueFieldType == Integer.class) {
    int valueCast = Integer.parseInt(proValue);
    method.invoke(o, valueCast);
    } else if (valueFieldType == Float.class || valueFieldType == float.class) {
    float valueCast2 = Float.parseFloat(proValue);
    method.invoke(o, valueCast2);
    } else if (valueFieldType == double.class || valueFieldType == Double.class) {
    double valueCast3 = Double.parseDouble(proValue);
    method.invoke(o, valueCast3);
    }else {
    method.invoke(o, proValue);
    }
    } catch(Exception e){
    throw new RuntimeException(e);
    }
    }
    }
    }
    }

不足

  • aop
  • 注解