0%

Spring-手写框架流程

手写框架流程,附上了获取bean和创建bean的代码,为附上加载配置文件,生成bean定义的代码

一.准备环境

1.导入依赖

2.写xml配置文件

3.编写测试代码

二.写框架

1.加载并解析配置文件

​ 涉及到Bedifinition

2.创建Bean实例

  1. 判断单例缓存Map中是否存在需要的实例

    1. 存在

      返回单例实例

    2. 不存在

      创建实例

      1. 获取Bedifinition,判断是否为null

        1. null,return null

        2. 判断是单例还是多例

          1. 单例

            1. 创建实例

            2. 创建bean的实例

              1. 注入属性

              2. 是否有初始化方法

              3. 有

                1. 执行方法 通过反射
              4. 无

              5. 是否有后置处理方法

              6. 有

                1. 通过aop处理
            3. 加入缓存Map

            4. 返回实例对象

          2. 多例

            1. 创建实例

            2. 返回实例对象

创建bean实例简化代码,只实现核心部分

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
private Map<String, BeanDefinition> beanDefinitions = new HashMap<>();
// 单例缓存
Map<String, Object> beans = new HashMap<String, Object>();

@Override
public void registerBeanDefinition(String beanName, BeanDefinition bd) {
beanDefinitions.put(beanName, bd);
}

@Override
public BeanDefinition getBeanDefinition(String beanName) {
return beanDefinitions.get(beanName);
}

// @Override
public Object getBean2(String name) {

// 从单例缓存获取实例对象
Object object = beans.get(name);
// 有实例对象时返回实现对象
if (object != null) {
return object;
}
// 没有实例对象,创建实例对象
// 获取Bedifinition,类的定义
BeanDefinition beanDefinition = getBeanDefinition(name);
// 没有类的定义时返回实例null
if (beanDefinition == null) {
return null;
}
// 获取单例多例属性,判断多例还是单例
String scope = beanDefinition.getScope();
if ("singleton".equals(scope)) {
// 单例:
// 一、创建实例
Object bean = creaBean2(name, beanDefinition);
// 二、加入单例缓存
beans.put(name, bean);
// 三、返回单例实例
return bean;
} else if ("prototype".equals(scope)) {
// 多例:
// 一、创建实例
// 二、返回实例
return creaBean2(name, beanDefinition);
}
return object;
}

private Object creaBean2(String name, BeanDefinition beanDefinition) {
// 1.创建bean的实例
// 1.1获取类的类型
String clazzName = beanDefinition.getClazzName();
// 1.2创建
Class<?> type = null;
try {
type = Class.forName(clazzName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object bean = ReflectUtils.createObject(type);
// 2.注入属性
List<PropertyValue> propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues) {
// 类属性名称
String name2 = propertyValue.getName();
// 类属性值 分两种,普通类型value和引用类型ref propertity中的value标签中的内容
Object value = propertyValue.getValue();

Object valueToUse = null;
// 判断普通类型or引用类型
if (value instanceof TypedStringValue) {// 判断是否为普通类型
TypedStringValue typedStringValue = (TypedStringValue) value;
String stringValue = typedStringValue.getValue();
Class<?> targetType = typedStringValue.getTargetType();

// 只匹配了两种Integer和String
if (targetType == Integer.class) {
// 确定了value的类型为Integer,注入属性 name2:属性名称:age;valueToUse:属性值:18
valueToUse = Integer.parseInt(stringValue);
} else if (targetType == String.class) {
valueToUse = stringValue;
}

} else if (value instanceof RuntimeBeanReference) {// 判断是否为引用类型
RuntimeBeanReference runtimeBeanReference = (RuntimeBeanReference) value;
String ref = runtimeBeanReference.getRef();

// TODO 容易引起循环依赖问题
// 获取引用类型的属性,并注入。获取引用类型时,需要把引用类型Course中的属性name和age先注入到Course中
valueToUse = getBean2(ref);
}
// 设置属性
ReflectUtils.setProperty(bean, name2, valueToUse);
}
// 3.处理初始化方法
String initMethod = beanDefinition.getInitMethod();
if ("init".equals(initMethod)) {
ReflectUtils.invokeMethod(bean, initMethod);
}
// 4.处理后置方法 aop

return bean;
}