您的位置:首页 > 编程语言 > Java开发

编码剖析Spring依赖注入的原理

2015-08-08 10:33 726 查看
1.创建一个PersonDao对象,如下代码:

package cn.itcast.dao;

public interface PersonDao {

public void add();
}


package cn.itcast.dao.impl;

import cn.itcast.dao.PersonDao;

public class PersonDaoBean implements PersonDao {

public void add(){
System.out.println("执行PersonDaoBean中的add()方法.");
}

}


2.将PersonDao对象注入到PersonService中

第一种,通过setter方法

package cn.itcast.service.impl;

import cn.itcast.dao.PersonDao;
import cn.itcast.service.PersonService;

public class PersonServiceBean implements PersonService {

private PersonDao  personDao;

public void setPersonDao(PersonDao personDao){
this.personDao = personDao;
}

@Override
public void save() {
personDao.add();
}
}
这里并没有出现PersonDaoBean,实现了完全解耦。那么如何在配置文件中注入PersonDaoBean呢?

<bean id="personDao" class="cn.itcast.dao.impl.PersonDaoBean"></bean>
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"
init-method="init" destroy-method="destroy">
<property name="personDao" ref="personDao"></property><!-- 注入 -->
</bean>
由容器帮我们创建依赖对象,并且由容器注入进来,这就是控制反转。

它的内部是如何实现注入过程的呢?
<property name="personDao" ref="personDao"></property>


在bean,元素底下是有多个属性元素的。我们也可以指定多个属性,为多个属性注入值。

我们可以建立一个属性的javaBean,来存放属性的信息,然后将属性的javaBean放入一个集合,存放到Bean中。

然后修改读取配置文件的方法,创建查询路径。具体添加代码如下:

XPath propertysub = element.createXPath("ns:property"); // 通过相对路径创建查询路径
propertysub.setNamespaceURIs(nsMap); // 设置命名空间
List<Element> properties = propertysub.selectNodes(element);
for(Element property : properties) {
String propertyName = property.attributeValue("name");
String propertyRef = property.attributeValue("ref");
System.out.println("propertyName : " + propertyName + " propertyRef: " + propertyRef); // 用于测试
PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyRef);
beanDefine.getProperties().add(propertyDefinition);
}


测试代码:

@Test
public void instanceSpring() {
ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml");
}
后台打印结果为:

propertyName : personDao propertyRef: personDao
我被实例化了...


怎样根据ref的值将bean注入到有属性指令的bean里面去呢?现在我们来处理注入功能

可以用一下代码实现:

/**
* 为bean对象的属性注入值
*/
private void injectObjec() {
// 循环所有的bean
for(BeanDefinition beanDefinition : beanDefines) {
// 根据beanDefinition的id获得实例化的bean
Object bean = sigletons.get(beanDefinition.getId());
if(bean != null) {
try {
// 取得bean实例的属性描述
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
//取得配置文件bean里面的所有属性定义
for(PropertyDefinition propertyDefinition : beanDefinition.getProperties()){
// 判读这个属性是否在bean定义的属性里面,如果存在,再通过反射技术把这个值注入进去。
for(PropertyDescriptor properdesc : ps) {
if(propertyDefinition.getName().equals(properdesc.getName())) {
Method setter = properdesc.getWriteMethod(); // 获取属性的setter方法
if(setter!=null){
Object value = sigletons.get(propertyDefinition.getRef());
setter.setAccessible(true); // 当setter方法为私有方法时,设置它允许访问
setter.invoke(bean, value); // 把引用对象注入到属性中
}
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}


再来编写测试代码,

@Test
public void instanceSpring() {
ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml");
PersonService personService = (PersonService)ctx.getBean("personService");
personService.save();
}
如果后台打印出了PersonDaoBean中的add方法的输出语句,则表示注入成功。测试结果为:



整个就是依赖注入的原理了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: