使用Spring可以通过控制反转把依赖对象交给Spring管理,并把依赖对象通过外部容器动态的注入到组件内部。
下面将演示如何将依赖对象注入到组件中。
首先我们新建一个PersonDaoBean,然后将其注入到PersonServiceBean中。
PersonDaoBean.Java
package xjj.dao.impl;
import xjj.dao.PersonDao;
public class PersonDaoBean implements PersonDao {
@Override
public void add(){
System.out.println("执行PersonDaoBean中的add()方法");
}
}
由于我们是面对接口编程,抽取PersonDaoBean的接口类PersonDao:
PersonDao.java
package xjj.dao;
public interface PersonDao {
public abstract void add();
}
如何将PersonDaoBean注入到PersonServiceBean中去的呢?
注入方式有两种:
第一种是根据构造器参数注入
第二种是使用属性的setter方法注入
当我们通过属性的setter方法注入时,一定不要忘了给属性添加setter方法。
package xjj.service.impl;
import xjj.dao.PersonDao;
import xjj.service.PersonService;
public class PersonServiceBean implements PersonService {
private PersonDao personDao;
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
public PersonDao getPersonDao() {
return personDao;
}
@Override
public void save(){
personDao.add();
}
}
通过引用dao层接口,来调用dao实现类的方法,这样实现了service层和dao层的彻底解耦。
当我们要为PersonServiceBean注入PersonDaoBean时,首先要把PersonDaoBean添加到Spring容器中去,然后通过bean的子元素property,实现属性注入
属性的名称是getPersonDao方法去掉get首字母小写,ref是需要注入的bean的名称(ID),Spring会根据名称从Spring容器中获取bean,然后把这个bean通过反射技术赋给了属性。
beans.xml
方式1:用ref属性
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="personDao" class="xjj.dao.impl.PersonDaoBean" ></bean>
<bean id="personService" class="xjj.service.impl.PersonServiceBean" >
<property name="personDao" ref="personDao"></property>
</bean>
</beans>
方式2:用内部bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="personService" class="xjj.service.impl.PersonServiceBean" >
<property name="personDao" >
<bean class="xjj.dao.impl.PersonDaoBean"/>
</property>
</bean>
</beans>
问题:为什么在PersonServiceBean.java文件中添加带有参数的构造方法时,注入失败????
public PersonServiceBean(PersonDao personDao) {
this.personDao = personDao;
}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personService' defined in class path resource [beans.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [xjj.service.impl.PersonServiceBean]: <span style="color:#ff0000;">No default constructor found;</span> nested exception is java.lang.NoSuchMethodException: xjj.service.impl.PersonServiceBean.<init>()
原因:由于人为添加了带参数的构造方法
如果改成默认构造方法或者直接将构造方法删掉就不会出错了。
public PersonServiceBean() {
}
然后测试注入是否成功,我们在save方法中调用PersonDaoBean的add方法,如果注入不成功会出现空指针异常;
SpringTest.java
package junit.test;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import xjj.service.PersonService;
public class SpringTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@Test
public void test() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
PersonService personService = (PersonService) ctx.getBean("personService");
personService.save();
}
}
优缺点:采用第一种ref方式时,PersonDaoBean可以为多个bean服务,但是内部bean的方式,只能为一个bean服务。
测试结果:
构造器注入:
PersonServiceBean.java
package xjj.service.impl;
import xjj.dao.PersonDao;
import xjj.service.PersonService;
public class PersonServiceBean implements PersonService {
private PersonDao PersonDao;
private String name;
public PersonServiceBean(PersonDao personDao,String name){
super();
this.PersonDao = personDao;
this.name = name;
}
public PersonDao getPersonDao() {
return PersonDao;
}
public void setPersonDao(PersonDao personDao) {
PersonDao = personDao;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void save(){
PersonDao.add();
System.out.println(name);
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="personDao" class="xjj.dao.impl.PersonDaoBean"></bean>
<bean id="personService" class="xjj.service.impl.PersonServiceBean" >
<!-- 索引index从0开始,一次代表构造函数的参数 -->
<constructor-arg index="0" type="xjj.dao.PersonDao" ref="personDao"/>
<constructor-arg index="1" value="xjj"/>
</bean>
</beans>
结果: