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

13 篇文章 0 订阅

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方法的输出语句,则表示注入成功。测试结果为:

整个就是依赖注入的原理了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zerlinda_Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值