@@ -46,16 +46,104 @@ helloWorldService.helloWorld();
46
46
47
47
git checkout step-3-inject-bean-with-property
48
48
49
+ 这一步,我们想要为bean注入属性。我们选择将属性注入信息保存成` PropertyValue ` 对象,并且保存到` BeanDefinition ` 中。这样在初始化bean的时候,我们就可以根据PropertyValue来进行bean属性的注入。Spring本身使用了setter来进行注入,这里为了代码简介,我们使用Field的形式来注入。
50
+
51
+ ``` java
52
+ // 1.初始化beanfactory
53
+ BeanFactory beanFactory = new AutowireCapableBeanFactory ();
54
+
55
+ // 2.bean定义
56
+ BeanDefinition beanDefinition = new BeanDefinition ();
57
+ beanDefinition. setBeanClassName(" us.codecraft.tinyioc.HelloWorldService" );
58
+
59
+ // 3.设置属性
60
+ PropertyValues propertyValues = new PropertyValues ();
61
+ propertyValues. addPropertyValue(new PropertyValue (" text" , " Hello World!" ));
62
+ beanDefinition. setPropertyValues(propertyValues);
63
+
64
+ // 4.生成bean
65
+ beanFactory. registerBeanDefinition(" helloWorldService" , beanDefinition);
66
+
67
+ // 5.获取bean
68
+ HelloWorldService helloWorldService = (HelloWorldService ) beanFactory. getBean(" helloWorldService" );
69
+ helloWorldService. helloWorld();
70
+
71
+ ```
72
+
49
73
## 4.step4-读取xml配置来初始化bean
50
74
51
75
git checkout step-4-config-beanfactory-with-xml
76
+
77
+ 这么大一坨初始化代码让人心烦。这里的` BeanDefinition ` 只是一些配置,我们还是用xml来初始化吧。我们定义了` BeanDefinitionReader ` 初始化bean,它有一个实现是` XmlBeanDefinitionReader ` 。
78
+
79
+ ``` java
80
+ // 1.读取配置
81
+ XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader (new ResourceLoader ());
82
+ xmlBeanDefinitionReader. loadBeanDefinitions(" tinyioc.xml" );
83
+
84
+ // 2.初始化BeanFactory并注册bean
85
+ BeanFactory beanFactory = new AutowireCapableBeanFactory ();
86
+ for (Map . Entry<String , BeanDefinition > beanDefinitionEntry : xmlBeanDefinitionReader. getRegistry(). entrySet()) {
87
+ beanFactory. registerBeanDefinition(beanDefinitionEntry. getKey(), beanDefinitionEntry. getValue());
88
+ }
89
+
90
+ // 3.获取bean
91
+ HelloWorldService helloWorldService = (HelloWorldService ) beanFactory. getBean(" helloWorldService" );
92
+ helloWorldService. helloWorld();
93
+ ```
52
94
53
95
## 5.step5-为bean注入bean
54
96
55
97
git checkout step-5-inject-bean-to-bean
98
+
99
+ 使用xml配置之后,似乎里我们熟知的Spring更近了一步!但是现在有一个大问题没有解决:我们无法处理bean之间的依赖,无法将bean注入到bean中,所以它无法称之为完整的IoC容器!如何实现呢?我们定义一个` BeanReference ` ,来表示这个属性是对另一个bean的引用。这个在读取xml的时候初始化,并在初始化bean的时候,进行解析和真实bean的注入。
100
+
101
+ ``` java
102
+ for (PropertyValue propertyValue : mbd. getPropertyValues(). getPropertyValues()) {
103
+ Field declaredField = bean. getClass(). getDeclaredField(propertyValue. getName());
104
+ declaredField. setAccessible(true );
105
+ Object value = propertyValue. getValue();
106
+ if (value instanceof BeanReference ) {
107
+ BeanReference beanReference = (BeanReference ) value;
108
+ value = getBean(beanReference. getName());
109
+ }
110
+ declaredField. set(bean, value);
111
+ }
112
+ ```
113
+
114
+ 同时为了解决循环依赖的问题,我们使用lazy-init的方式,将createBean的事情放到` getBean ` 的时候才执行,是不是一下子方便很多?这样在注入bean的时候,如果该属性对应的bean找不到,那么就先创建!因为总是先创建后注入,所以不会存在两个循环依赖的bean创建死锁的问题。
115
+
116
+ ``` java
117
+ // 1.读取配置
118
+ XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader (new ResourceLoader ());
119
+ xmlBeanDefinitionReader. loadBeanDefinitions(" tinyioc.xml" );
120
+
121
+ // 2.初始化BeanFactory并注册bean
122
+ AbstractBeanFactory beanFactory = new AutowireCapableBeanFactory ();
123
+ for (Map . Entry<String , BeanDefinition > beanDefinitionEntry : xmlBeanDefinitionReader. getRegistry(). entrySet()) {
124
+ beanFactory. registerBeanDefinition(beanDefinitionEntry. getKey(), beanDefinitionEntry. getValue());
125
+ }
126
+
127
+ // 3.初始化bean
128
+ beanFactory. preInstantiateSingletons();
129
+
130
+ // 4.获取bean
131
+ HelloWorldService helloWorldService = (HelloWorldService ) beanFactory. getBean(" helloWorldService" );
132
+ helloWorldService. helloWorld();
133
+ ```
56
134
57
135
## 6.step6-ApplicationContext登场
58
136
59
137
git checkout step-6-invite-application-context
138
+
139
+ 现在BeanFactory的功能齐全了,但是使用起来有点麻烦。于是我们引入熟悉的` ApplicationContext ` 接口,并在` AbstractApplicationContext ` 的` refresh() ` 方法中进行bean的初始化工作。
140
+
141
+ ``` java
142
+ ApplicationContext applicationContext = new ClassPathXmlApplicationContext (" tinyioc.xml" );
143
+ HelloWorldService helloWorldService = (HelloWorldService ) applicationContext. getBean(" helloWorldService" );
144
+ helloWorldService. helloWorld();
145
+ ```
146
+
147
+ 是不是非常熟悉?至此为止,我们的tiny-spring的IoC部分可说完工了。这部分的类、方法命名和作用,都是对应Spring中相应的组件。虽然代码量只有400多行,但是已经有了基本的IoC功能!
60
148
61
149
# AOP
0 commit comments