咱们前面说的案例,要给UserServiceImpl中的成员属性UserDao赋值,用的是在UserServiceImpl中创建setter方法.然后在配置文件中配置如下的标签
<bean id="userservice" class="service.impl.UserServiceImpl">
<property name="dao" ref="userdao"></property>
</bean>
注意:<bean>中使用<property>子标签是使用无参构造+setter方法创建我们需要的对象的
但是我们前面还说过,可以使用UserServiceImpl的构造方法来给员属性UserDao赋值.那我们现在看一下:首先我们修改一下UserServiceImpl类的代码:
package service.impl;
import dao.UserDao;
import service.UserService;
public class UserServiceImpl implements UserService {
private UserDao dao;
//构造器
public UserServiceImpl(UserDao dao) {
super();
this.dao = dao;
}
//set方法
/*public void setDao(UserDao dao) {
this.dao = dao;
}*/
@Override
public void addUser() {
dao.addUser();
}
@Override
public void deleteUser() {
dao.deleteUser();
}
}
如果我们不修改配置文件,直接来在原来的测试类Test中运行,那会出现什么情况呢?
这时候会出现下面的异常:没有找到默认的构造器,也就是缺少无参构造
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userservice' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [service.impl.UserServiceImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: service.impl.UserServiceImpl.<init>()
所以我们知道了,如果<bean>中使用<property>字标签是默认调用无参的构造器和setter方法来创建的对象的.那我们这里通过有参构造来实现该适合操作呢? ---我们使用<bean>中的<constructor-arg>这个字标签来实现
<?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.xsd">
<bean id="userdao" class="dao.impl.UserDaoImpl"></bean>
<!-- 测试类中首先要得到一个UserService的实现类对象 我们做如下配置-->
<!-- 使用无参构造+setter方法创建对象 -->
<!-- <bean id="userservice" class="service.impl.UserServiceImpl">
<property name="dao" ref="userdao"></property>
</bean> -->
<!-- 使用有参构造 -->
<bean id="userservice" class="service.impl.UserServiceImpl">
<!-- 构造器参数: name:参数名称 value:简单类型 ref:引用
这里面的name,value,ref和上面的使用setter方法的方式中<property>的属性含义一样 -->
<constructor-arg name = "dao" ref = "userdao"></constructor-arg>
</bean>
</beans>
此时我们在运行,结果就会正常显示"添加用户""删除用户"的正确结果了.除了上面这一种方式,其实还有第二种使用有参构造来创建对象的方法.我们从constructor-arg 这个标签里还发现一些别的东西里面除了name,ref属性之外还有下面两个属性:
index:参数的索引 第几个参数 从0开始
type:参数类型的类型
我们来看一下用法:
<?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.xsd">
<bean id="userdao" class="dao.impl.UserDaoImpl"></bean>
<!-- 测试类中首先要得到一个UserService的实现类对象 我们做如下配置-->
<!-- 使用无参构造+setter方法创建对象 -->
<!-- <bean id="userservice" class="service.impl.UserServiceImpl">
<property name="dao" ref="userdao"></property>
</bean> -->
<!-- 使用有参构造 -->
<bean id="userservice" class="service.impl.UserServiceImpl">
<constructor-arg index = "0" ref = "userdao"></constructor-arg>
</bean> -->
</beans>
我们构造参数只需要传入一个对象参数,所以种类index的值自然就是0了,我们依旧可以用ref来给这个位于index=0的属性赋值.
为什么需要两种方式呢?其实是因为有些代码不是我们自己写的,咱们在没有源码的情况下调用方法时,方法形式参数的显示的是arg0,arg1..例如下面这样
为了解决这种没有解释不容易辨认的情况.所以给了第二种,哪怕我们不知道参数名字,但是知道位置也可以创建对象.
注意:上面我们通过工厂模式创建的对象都是只有一个成员属性;不管是通过无参构造+setter方法 还是 有参构造 来创建对象,如果成员属性不只一个,那我么只要在配置文件中为每一个属性都配置一个<property>或<constructor-arg>标签即可.2个成员属性就写两个<property>或<constructor-arg>子标签这样.