首页 > 其他 > 详细

Spring的DI(Ioc) - 注入bean

时间:2014-02-21 09:29:27      阅读:518      评论:0      收藏:0      [点我收藏+]

注入bean有两种方式:

1
2
3
4
5
6
7
8
9
10
11
12
注入其他bean:
方式一
<bean id="orderDao" class="cn.itcast.service.OrderDaoBean"/>
<bean id="orderService" class="cn.itcast.service.OrderServiceBean">
    <property name="orderDao" ref="orderDao"/>
</bean>
方式二(使用内部bean,但该bean不能被其他bean使用)
<bean id="orderService" class="cn.itcast.service.OrderServiceBean">
    <property name="orderDao">
        <bean class="cn.itcast.service.OrderDaoBean"/>
    </property>
</bean>

  

一般我们的工程在service层依赖dao层的实现来实现业务逻辑。

service层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PersonServiceImpl implements PersonService {
     
    private PersonDao personDao;
     
    @Override
    public void save() {
        personDao.save();
        System.out.println("service :  " + " save 方法");
    }
    public PersonDao getPersonDao() {
        return personDao;
    }
    public void setPersonDao(PersonDao personDao) {
        this.personDao = personDao;
    }
}

  

dao层:

1
2
3
4
5
6
public class PersonDaoImpl implements PersonDao {
    @Override
    public void save() {
        System.out.println("dao层的save方法");
    }
}

  

beans.xml的配置

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
            
    <bean id="personDaoImpl" class="cn.gbx.dao.PersonDaoImpl"></bean>
    <bean id="personServiceImpl" class="cn.gbx.serviceimpl.PersonServiceImpl" >
        <property name="personDao" ref="personDaoImpl"></property>
    </bean>
</beans>

  

测试方法:

1
2
3
4
5
6
7
8
public class SpringTest {
    @Test
    public void spring1() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        PersonService ps = (PersonService)ctx.getBean("personServiceImpl");
        ps.save();
    }
}

  

然后我们就实现了Spring对bean对象的依赖注入。 service层所依赖的dao层的PersonDao对象不是由service本身去创建管理,而是交给了第三方容器Spring去管理。

那么Spring是如何管理的呢?

我们可想而知

1: 首先必须解析XML 将 <bean>标签和 <property>标签都解析出来

2: 利用反射实例话对象

3: 利用内省将实例化完成的对象注入到有依赖的对象里面

 

我们可以自己模拟实现:

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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package cn.gbx.myExample;
 
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
 
public class MyClassPathXmlApplicationContext {
 
    private List<DefBean> defBeans = new ArrayList<DefBean>();  //存储<bean>标签的信息
    private Map<String, Object> singltons = new HashMap<String, Object>(); //存储读出来的对象
     
     
    public MyClassPathXmlApplicationContext() {
        super();
    }
 
    public MyClassPathXmlApplicationContext(String filename) {
        this.readXML(filename);
        this.instanceBean();
        this.injectProperty();
    }
    //利用内省将属性注入
    private void injectProperty() {
        for (DefBean defBean : defBeans) {
            Object bean = singltons.get(defBean.getId());
            if (bean != null) {
                //要想将依赖的对象注入,我们就要通过内省来操作对象的属性
                try {
                    BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
                    PropertyDescriptor[] ps = beanInfo.getPropertyDescriptors();
                 
                    for (DefProperty p : defBean.getDefPropertys()) {
                        for (PropertyDescriptor propertyDes : ps) {
                            if (propertyDes.getName().equals(p.getName())) {
                                Method setter = propertyDes.getWriteMethod();
                                if (setter != null) {
                                    Object value = singltons.get(p.getRef());
                                    setter.setAccessible(true); //这样即使set方法是私有的都可以访问
                                    setter.invoke(bean, value); //把引用对象注入到bean属性里面
                                }
                                break;
                            }
                        }
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
         
    }
    //利用反射实例化对象
    private void instanceBean() {
        for (DefBean bean : defBeans) {
            //输出测试读取的xml
            /*System.out.println(bean.getId() + "  : " + bean.getClassName());
            System.out.println("------------------------");
            for (DefProperty p : bean.getDefPropertys()) {
                System.out.println("Property : name = " + p.getName() + "  :  ref = " + p.getRef());
            }
            */
             
            if (bean.getClassName() != null && !"".equals(bean.getClassName())) {
                try {
                    singltons.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
 
    private void readXML(String filename) {
        SAXReader reader = new SAXReader();
        Document document = null;
        URL xmlPath = this.getClass().getClassLoader().getResource(filename);
        try {
            document = reader.read(xmlPath);
            //创建命名空间
            Map<String, String> nsMap = new HashMap<String, String>();
            nsMap.put("ns", "http://www.springframework.org/schema/beans");
             
            //创建查询路径
            XPath xsub = document.createXPath("//ns:beans/ns:bean");
            xsub.setNamespaceURIs(nsMap); // 设置命名空间
             
            List<Element> elements = xsub.selectNodes(document);
             
            DefBean defBean = null;
            for (Element e : elements) {
                String id = e.attributeValue("id");
                String className = e.attributeValue("class");
                defBean = new DefBean(id, className);
                 
                //为<bean>节点设置查询路径
                XPath xPropertySub = e.createXPath("ns:property");
                xPropertySub.setNamespaceURIs(nsMap);
                List<Element> propertys =  xPropertySub.selectNodes(e);
                 
                DefProperty defProperty = null;
                for (Element e2 : propertys) {
                    String name = e2.attributeValue("name");
                    String ref = e2.attributeValue("ref");
                     
                    defProperty = new DefProperty(name, ref);
                    defBean.getDefPropertys().add(defProperty);
                }
                 
                defBeans.add(defBean);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
         
    }
    public Object getBean(String key) {
        return singltons.get(key);
    }
     
     
}

  

Spring的DI(Ioc) - 注入bean

原文:http://www.cnblogs.com/E-star/p/3558346.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!