[Spring实战系列](7)Spring注入方式之构造器注入
2016-02-03 18:39
429 查看
1.构造器注入
基于构造器的注入通过调用带参数的构造器来实现,每个参数代表着一个协作者。
1.1最简单形式
我们以下面的Student实体类为例进行说明:
Student类有四个属性:name,company,age,sex。这四个属性是通过构造器注入来设置。重写Student的toString()方法来展示Student对象信息。
基于构造器的注入通过调用带参数的构造器来实现,每个参数代表着一个协作者。
1.1最简单形式
我们以下面的Student实体类为例进行说明:
[code]packagecom.sjf.bean;
/**
*学生实体类
*@authorsjf0115
*
*/
publicclassStudent{
privateStringname;
privateStringcompany;
privateintage;
privatebooleansex;
publicStudent(Stringname,Stringcompany,intage,booleansex){
this.name=name;
this.company=company;
this.age=age;
this.sex=sex;
}
@Override
publicStringtoString(){
StringBuilderstringBuilder=newStringBuilder();
stringBuilder.append("个性详细信息如下:"+"\n");
stringBuilder.append("name:"+name+"\n");
stringBuilder.append("company:"+company+"\n");
stringBuilder.append("age:"+age+"\n");
stringBuilder.append("sex:"+(sex?"boy":"girl"));
returnstringBuilder.toString();
}
}
Student类有四个属性:name,company,age,sex。这四个属性是通过构造器注入来设置。重写Student的toString()方法来展示Student对象信息。
[code]<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans 'target='_blank'>http://www.springframework.org/schema/beans/spring-beans.xsd"><beanid="yoona"class="com.sjf.bean.Student"><constructor-argvalue="yoona"/><constructor-argvalue="Facebook"/><constructor-argvalue="24"/><constructor-argvalue="true"/></bean></beans>
运行结果:[code]name:yoonacompany:Facebookage:24sex:true
1.2根据type属性传值
bean中的constructor-arg元素用于通过构造器注入来设置属性。因为Student类中只有一个构造器,所以该代码没有任何问题。当有相同个数的构造器时,将会出现冲突。考虑如下:
我们为Student类提供了两个构造器:[code]publicStudent(Stringname,Stringcompany){this.name=name;this.company=company;}publicStudent(Stringname,intage){this.name=name;this.age=age;}
配置文件:[code]<beanid="yoona"class="com.sjf.bean.Student"><constructor-argvalue="yoona"/><constructor-argvalue="24"/></bean>
那么现在你认为哪个构造器将被调用?按照我们的思维应该是第二个带String和int参数的构造器,真的吗?实际上Spring将调用第一个构造器。即使我们知道第一个参数是String,第二个参数是int,但是Spring将其都解析为String。
运行结果:[code]name:yoonacompany:24
针对上面的这种情况,我们可以在构造器参数定义中使用type属性来显式的指定参数所对应的简单类型。现在如下配置,第二个构造器将被调用:[code]<beanid="yoona"class="com.sjf.bean.Student"><constructor-argtype="java.lang.String"value="yoona"/><constructor-argtype="int"value="24"/></bean>
这样设置之后value="24"则是int类型,不会被认为是String,所以只能匹配publicStudent(String
name,int
age)构造器。
运行结果:[code]name:yoonaage:24
1.3根据index属性传值
通过使用index属性可以显式的指定构造器参数出现顺序。指定构造器参数索引是使用构造器IoC首选的方式。
那么现在考虑如下情况。我们在Student类中有如下的构造器:[code]publicStudent(intage,Stringcompany){this.company=company;this.age=age;}publicStudent(Stringname,intage){this.name=name;this.age=age;}
进行如下配置:[code]<beanid="yoona"class="com.sjf.bean.Student"><constructor-argtype="java.lang.String"value="yoona"/><constructor-argtype="int"value="24"/></bean>
那么现在你认为哪个构造器将被调用?第二个?但是实际上调用了第一个构造器。在调用构造器,配置文件中定义的参数顺序并没有先后之分。
运行结果:[code]company:yoonaage:24
要解决该问题,需要指定index属性,配置如下:[code]<beanid="yoona"class="com.sjf.bean.Student"><constructor-argindex="0"value="yoona"/><constructor-argindex="1"value="24"/></bean>
这样设置之后,value="yoona"必须对应构造器中的第一个参数,所以只能匹配publicStudent(String
name,int
age)构造器。
运行结果:[code]name:yoonaage:24
1.4根据name属性传值
其实还有一个得推荐的方式:根据name属性进行匹配。针对上面的构造器我们使用name属性进行配置如下:[code]<beanid="yoona"class="com.sjf.bean.Student"><constructor-argname="name"value="yoona"/><constructor-argname="age"value="24"/></bean>
这样配置之后,value="yoona"只能对应name属性,value="24"只能对应age属性。
运行结果:[code]name:yoonaage:24
1.5通过构造器注入对象引用
我们为Student提供一个学校实体类:[code]packagecom.sjf.bean;/***学校实体类*@authorsjf0115**/publicclassSchool{privateStringname;privateStringlocation;publicSchool(Stringname,Stringlocation){this.name=name;this.location=location;}@OverridepublicStringtoString(){StringBuilderstringBuilder=newStringBuilder();stringBuilder.append("name:"+name);stringBuilder.append("location:"+location);returnstringBuilder.toString();}}
我们使用构造器注入的方式School类进行配置:[code]<beanid="xidian"class="com.sjf.bean.School"><constructor-argindex="0"value="西电"/><constructor-argindex="1"value="西安"/></bean>[code]packagecom.sjf.bean;/***学生实体类*@authorsjf0115**/publicclassStudent{privateStringname;privateSchoolschool;privateintage;publicStudent(Stringname,Schoolschool,intage){this.name=name;this.school=school;this.age=age;}@OverridepublicStringtoString(){StringBuilderstringBuilder=newStringBuilder();stringBuilder.append("个人详细信息如下:"+"\n");stringBuilder.append("name:"+name+"\n");stringBuilder.append("age:"+age+"\n");stringBuilder.append("school:"+school.toString());returnstringBuilder.toString();}}
为Student进行配置:[code]<beanid="yoona"class="com.sjf.bean.Student"><constructor-argname="name"value="yoona"/><constructor-argname="age"value="24"/><constructor-argname="school"ref="xidian"/></bean>
在这我们不能使用value属性为第二个构造参数赋值,因为School不是简单类型。取而代之的是,我们使用ref属性将ID为xidian的Bean引用传递给构造器。
相关文章推荐
- Java 连接各种数据库
- 根据wsdl生成java代码的方法总结
- 【Java】 批处理
- Java图片压缩处理
- java32:I/O
- java线程池
- SpringMVC验证码生成,点击刷新及验证--基于kaptcha
- Struts2之ModelDriven用法
- 基于注解的mybatis和spring整合
- Java项目开发环境构建工具 Gradle 使用笔记(简单、基本)
- 使用LS2J技术在LotusScript中使用Java
- Java数据类型转换
- JVM源码分析之javaagent原理完全解读
- Java基础:转义字符
- JDK Timer & TimerTask
- jar包导致的错误之java.lang.NoClassDefFoundError: org.achartengine.renderer.XYMultipleSeriesRe
- Spring框架学习(二)
- springMVC js等文件找不到解决方法
- 深入解析Java的设计模式编程中的模板方法模式
- Spring-web源码解析之Filter-CharacterEncodingFilter