Skip to content

Commit 7d39270

Browse files
committed
docs
1 parent 1b091c5 commit 7d39270

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

changelog.md

+88
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,104 @@ helloWorldService.helloWorld();
4646

4747
git checkout step-3-inject-bean-with-property
4848

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+
4973
## 4.step4-读取xml配置来初始化bean
5074

5175
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+
```
5294

5395
## 5.step5-为bean注入bean
5496

5597
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+
```
56134

57135
## 6.step6-ApplicationContext登场
58136

59137
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功能!
60148

61149
# AOP

0 commit comments

Comments
 (0)