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. 是否有初始化方法

                1. 执行方法 通过反射
              3. 是否有后置处理方法

                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;
}