注入依赖对象
基本类型对象注入:
<bean id="orderService" class="cn.itcast.service.OrderServiceBean">
<constructor-arg index=“0” type=“java.lang.String” value=“xxx”/>//构造器注入
<property name=“name” value=“zhao/>//属性setter方法注入
</bean>
注入其他bean:
方式一
<bean id="persionDao" class="cn.com.xinli.dao.impl.PersionDaoBean"></bean>
<bean id="persionServiceBean" class="cn.com.xinli.service.impl.PersionServiceBean" init-method="init" destroy-method="destory">
<property name="persionDao" ref="persionDao">
</property>
</bean>
方式二(使用内部bean,但该bean不能被其他bean使用)
<bean id="orderService" class="cn.itcast.service.OrderServiceBean">
<property name="orderDao">
<bean class="cn.com.xinli.dao.impl.PersionDaoBean"/>
</property>
</bean>
场景:有一个业务需要我们在service曾调用dao层的方法,一般的做法是我们在serivce层new一个dao参的对象,调用其中的方法,这样就会造成dao层和service层之间的耦合,下面我们使用spring中的 依赖注入 在service层 注入dao层的对象.
步骤:
(1).dao层PersionDao接口
package cn.com.xinli.dao;
public interface PersionDao
{
public abstract void add();
}
(2) 接口实现PersionDaoBean
package cn.com.xinli.dao.impl;
import org.apache.log4j.Logger;
import cn.com.xinli.dao.PersionDao;
public class PersionDaoBean implements PersionDao
{
Logger log=Logger.getLogger(PersionDaoBean.class);
/* (non-Javadoc)
* @see cn.com.xinli.dao.impl.PersionDao#add()
*/
public void add()
{
log.info("执行了PersionDaoBean中的add()方法");
}
}
(3) 在service 层,我们要把dao层的对象 注入 进来
package cn.com.xinli.service.impl;
import org.apache.log4j.Logger;
import cn.com.xinli.dao.PersionDao;
import cn.com.xinli.service.PersionSevice;
public class PersionServiceBean implements PersionSevice
{
Logger log=Logger.getLogger(PersionServiceBean.class);
private PersionDao persionDao;
public PersionDao getPersionDao()
{
return persionDao;
}
public void setPersionDao(PersionDao persionDao)
{
this.persionDao = persionDao;
}
public void init()
{
log.info("初始化资源");
}
public PersionServiceBean()
{
log.info("我被实例化了");
}
public void save()
{
this.persionDao.add();
}
public void destory()
{
log.info("释放资源");
}
}
(4) 配置bean.xml
<bean id="persionDao" class="cn.com.xinli.dao.impl.PersionDaoBean"></bean>
<bean id="persionServiceBean" class="cn.com.xinli.service.impl.PersionServiceBean" init-method="init" destroy-method="destory">
<property name="persionDao" ref="persionDao"></property>
</bean>
其中 property 标签的 name属性 标识我们需要注入的属性的名字,对应了persionServiceBean 的一个属性, ref 属性是将bean.xm中声明的哪个bean 注入到 name 申明的属性中去
(5)测试
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
PersionSevice ps=(PersionSevice)ctx.getBean("persionServiceBean");
ps.save();
(6) 结果:这样就完成了依赖对象的创建和注入
2009-05-29 09:42:23,265 INFO (PersionDaoBean.java:15) - 执行了PersionDaoBean中的add()方法
深入理解: 模拟Spring容器属性注入的 ItcastClassPathXMLApplicationContext 容器,在以前的基础上修改,主要是理解spring容器是如何完成依赖对象的注入
/**
* 为属性注入值
*/
private void injectObject() {
for(BeanDefinition beanDefinition : beanDefines){
Object bean = sigletons.get(beanDefinition.getId());
if(bean!=null)
{
try
{
//得到bean对象所有的属性声明,返回的是一个数组
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys())
{
for(PropertyDescriptor properdesc : ps)
{
//如果xml中读取的属性名字是bean对象属性的名字
if(propertyDefinition.getName().equals(properdesc.getName()))
{
//setter方法是写方法
Method setter = properdesc.getWriteMethod();
//获取属性的setter方法 ,如果方法是private需要调用
if(setter!=null)
{
Object value = sigletons.get(propertyDefinition.getRef());
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
break;
}
}
}
}
catch (Exception e)
{
}
}
}
}
测试:换成 ItcastClassPathXMLApplicationContext 容器
ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml");
PersionSevice ps=(PersionSevice)ctx.getBean("persionServiceBean");
ps.save();
结果:2009-05-29 11:24:24,015 INFO (PersionDaoBean.java:15) - 执行了PersionDaoBean中的add()方法
使用bean的注入方式2 也能完成我们的业务,值需要修改bean.xml即可