Skip to content

Commit 9d0e1ed

Browse files
committed
inject with bean
1 parent 5bb19ae commit 9d0e1ed

9 files changed

Lines changed: 156 additions & 37 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package us.codecraft.tinyioc;
2+
3+
/**
4+
5+
*/
6+
public class BeanReference {
7+
8+
private String name;
9+
10+
private Object bean;
11+
12+
public BeanReference(String name) {
13+
this.name = name;
14+
}
15+
16+
public String getName() {
17+
return name;
18+
}
19+
20+
public void setName(String name) {
21+
this.name = name;
22+
}
23+
24+
public Object getBean() {
25+
return bean;
26+
}
27+
28+
public void setBean(Object bean) {
29+
this.bean = bean;
30+
}
31+
}

src/main/java/us/codecraft/tinyioc/factory/AbstractBeanFactory.java

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import us.codecraft.tinyioc.BeanDefinition;
44

5+
import java.util.ArrayList;
6+
import java.util.Iterator;
7+
import java.util.List;
58
import java.util.Map;
69
import java.util.concurrent.ConcurrentHashMap;
710

@@ -12,23 +15,40 @@ public abstract class AbstractBeanFactory implements BeanFactory {
1215

1316
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
1417

18+
private final List<String> beanDefinitionNames = new ArrayList<String>();
19+
1520
@Override
16-
public Object getBean(String name) {
17-
return beanDefinitionMap.get(name).getBean();
21+
public Object getBean(String name) throws Exception {
22+
BeanDefinition beanDefinition = beanDefinitionMap.get(name);
23+
if (beanDefinition == null) {
24+
throw new IllegalArgumentException("No bean named " + name + " is defined");
25+
}
26+
Object bean = beanDefinition.getBean();
27+
if (bean == null) {
28+
bean = doCreateBean(beanDefinition);
29+
}
30+
return bean;
1831
}
1932

2033
@Override
21-
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception {
22-
Object bean = doCreateBean(beanDefinition);
23-
beanDefinition.setBean(bean);
24-
beanDefinitionMap.put(name, beanDefinition);
25-
}
26-
27-
/**
28-
* 初始化bean
29-
* @param beanDefinition
30-
* @return
31-
*/
32-
protected abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception;
34+
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception {
35+
beanDefinitionMap.put(name, beanDefinition);
36+
beanDefinitionNames.add(name);
37+
}
38+
39+
public void preInstantiateSingletons() throws Exception {
40+
for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
41+
String beanName = (String) it.next();
42+
getBean(beanName);
43+
}
44+
}
45+
46+
/**
47+
* 初始化bean
48+
*
49+
* @param beanDefinition
50+
* @return
51+
*/
52+
protected abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception;
3353

3454
}

src/main/java/us/codecraft/tinyioc/factory/AutowireCapableBeanFactory.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package us.codecraft.tinyioc.factory;
22

33
import us.codecraft.tinyioc.BeanDefinition;
4+
import us.codecraft.tinyioc.BeanReference;
45
import us.codecraft.tinyioc.PropertyValue;
56

67
import java.lang.reflect.Field;
@@ -15,6 +16,7 @@ public class AutowireCapableBeanFactory extends AbstractBeanFactory {
1516
@Override
1617
protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
1718
Object bean = createBeanInstance(beanDefinition);
19+
beanDefinition.setBean(bean);
1820
applyPropertyValues(bean, beanDefinition);
1921
return bean;
2022
}
@@ -27,7 +29,12 @@ protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Excep
2729
for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {
2830
Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
2931
declaredField.setAccessible(true);
30-
declaredField.set(bean, propertyValue.getValue());
32+
Object value = propertyValue.getValue();
33+
if (value instanceof BeanReference) {
34+
BeanReference beanReference = (BeanReference) value;
35+
value = getBean(beanReference.getName());
36+
}
37+
declaredField.set(bean, value);
3138
}
3239
}
3340
}

src/main/java/us/codecraft/tinyioc/factory/BeanFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99
public interface BeanFactory {
1010

11-
Object getBean(String name);
11+
Object getBean(String name) throws Exception;
1212

1313
void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception;
1414
}

src/main/java/us/codecraft/tinyioc/xml/XmlBeanDefinitionReader.java

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.w3c.dom.NodeList;
77
import us.codecraft.tinyioc.AbstractBeanDefinitionReader;
88
import us.codecraft.tinyioc.BeanDefinition;
9+
import us.codecraft.tinyioc.BeanReference;
910
import us.codecraft.tinyioc.PropertyValue;
1011
import us.codecraft.tinyioc.io.ResourceLoader;
1112

@@ -57,22 +58,32 @@ protected void parseBeanDefinitions(Element root) {
5758
protected void processBeanDefinition(Element ele) {
5859
String name = ele.getAttribute("name");
5960
String className = ele.getAttribute("class");
60-
BeanDefinition beanDefinition = new BeanDefinition();
61-
processProperty(ele,beanDefinition);
62-
beanDefinition.setBeanClassName(className);
61+
BeanDefinition beanDefinition = new BeanDefinition();
62+
processProperty(ele, beanDefinition);
63+
beanDefinition.setBeanClassName(className);
6364
getRegistry().put(name, beanDefinition);
6465
}
6566

66-
private void processProperty(Element ele,BeanDefinition beanDefinition) {
67-
NodeList propertyNode = ele.getElementsByTagName("property");
68-
for (int i = 0; i < propertyNode.getLength(); i++) {
69-
Node node = propertyNode.item(i);
70-
if (node instanceof Element) {
71-
Element propertyEle = (Element) node;
72-
String name = propertyEle.getAttribute("name");
73-
String value = propertyEle.getAttribute("value");
74-
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name,value));
75-
}
76-
}
77-
}
67+
private void processProperty(Element ele, BeanDefinition beanDefinition) {
68+
NodeList propertyNode = ele.getElementsByTagName("property");
69+
for (int i = 0; i < propertyNode.getLength(); i++) {
70+
Node node = propertyNode.item(i);
71+
if (node instanceof Element) {
72+
Element propertyEle = (Element) node;
73+
String name = propertyEle.getAttribute("name");
74+
String value = propertyEle.getAttribute("value");
75+
if (value != null && value.length() > 0) {
76+
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value));
77+
} else {
78+
String ref = propertyEle.getAttribute("ref");
79+
if (ref == null || ref.length() == 0) {
80+
throw new IllegalArgumentException("Configuration problem: <property> element for property '"
81+
+ name + "' must specify a ref or value");
82+
}
83+
BeanReference beanReference = new BeanReference(ref);
84+
beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanReference));
85+
}
86+
}
87+
}
88+
}
7889
}
Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package us.codecraft.tinyioc;
22

33
import org.junit.Test;
4+
import us.codecraft.tinyioc.factory.AbstractBeanFactory;
45
import us.codecraft.tinyioc.factory.AutowireCapableBeanFactory;
5-
import us.codecraft.tinyioc.factory.BeanFactory;
66
import us.codecraft.tinyioc.io.ResourceLoader;
77
import us.codecraft.tinyioc.xml.XmlBeanDefinitionReader;
88

@@ -13,21 +13,40 @@
1313
*/
1414
public class BeanFactoryTest {
1515

16+
@Test
17+
public void testLazy() throws Exception {
18+
// 1.读取配置
19+
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
20+
xmlBeanDefinitionReader.loadBeanDefinitions("tinyioc.xml");
21+
22+
// 2.初始化BeanFactory并注册bean
23+
AbstractBeanFactory beanFactory = new AutowireCapableBeanFactory();
24+
for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) {
25+
beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
26+
}
27+
28+
// 3.获取bean
29+
HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
30+
helloWorldService.helloWorld();
31+
}
32+
1633
@Test
17-
public void test() throws Exception {
34+
public void testPreInstantiate() throws Exception {
1835
// 1.读取配置
1936
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
2037
xmlBeanDefinitionReader.loadBeanDefinitions("tinyioc.xml");
2138

2239
// 2.初始化BeanFactory并注册bean
23-
BeanFactory beanFactory = new AutowireCapableBeanFactory();
40+
AbstractBeanFactory beanFactory = new AutowireCapableBeanFactory();
2441
for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) {
2542
beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
2643
}
2744

28-
// 3.获取bean
45+
// 3.初始化bean
46+
beanFactory.preInstantiateSingletons();
47+
48+
// 4.获取bean
2949
HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
3050
helloWorldService.helloWorld();
31-
3251
}
3352
}

src/test/java/us/codecraft/tinyioc/HelloWorldService.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ public class HelloWorldService {
77

88
private String text;
99

10+
private OutputService outputService;
11+
1012
public void helloWorld(){
11-
System.out.println(text);
13+
outputService.output(text);
1214
}
1315

1416
public void setText(String text) {
1517
this.text = text;
1618
}
19+
20+
public void setOutputService(OutputService outputService) {
21+
this.outputService = outputService;
22+
}
1723
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package us.codecraft.tinyioc;
2+
3+
import org.junit.Assert;
4+
5+
/**
6+
7+
*/
8+
public class OutputService {
9+
10+
private HelloWorldService helloWorldService;
11+
12+
public void output(String text){
13+
Assert.assertNotNull(helloWorldService);
14+
System.out.println(text);
15+
}
16+
17+
public void setHelloWorldService(HelloWorldService helloWorldService) {
18+
this.helloWorldService = helloWorldService;
19+
}
20+
}

src/test/resources/tinyioc.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,13 @@
88
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
99
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
1010

11+
<bean name="outputService" class="us.codecraft.tinyioc.OutputService">
12+
<property name="helloWorldService" ref="helloWorldService"></property>
13+
</bean>
14+
1115
<bean name="helloWorldService" class="us.codecraft.tinyioc.HelloWorldService">
1216
<property name="text" value="Hello World!"></property>
17+
<property name="outputService" ref="outputService"></property>
1318
</bean>
1419

1520
</beans>

0 commit comments

Comments
 (0)