IOC控制翻转和依赖注入关系
- IOC的全称为(Inversion of Control),即“控制反转”;DI注入全称(Dependency Injection)依赖注入,二者是同一个事物的不同叫法,两者不是什么技术,而是一种设计思想。在Java开发中,IOC(DI)意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
- 换句话说是无需在方法内部去New一个新的对象,然后再利用New出来的对象去获取相应的值;而是利用ClassPathXmlApplicationContext(“applicationContext.xml”)属性去自己取得相应的值。
- 思想转换:由原来的自产自用,变为直接获取使用(从IOC容器中)。
三种常用的依赖注入方式
- 来用set方法注入(具体实例代码如下:)
实体类:
public class Teacher {
private String teacherName;
private int teacherAge;
public Teacher() {
}
public Teacher(String teacherName, int teacherAge) {
this.teacherName = teacherName;
this.teacherAge = teacherAge;
}
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
System.out.println("调用set方法");
this.teacherName = teacherName;
}
public int getTeacherAge() {
return teacherAge;
}
public void setTeacherAge(int teacherAge) {
this.teacherAge = teacherAge;
}
public void show() {
System.out.println("name:"+this.teacherName+"--age:"+this.teacherAge);
}
}
applicationContext.xml文件中的配置:
<bean id="teacher" class="org.dsl.entity.Teacher">
<property name="teacherName" value="zhangsan"></property>
<property name="teacherAge" value="20"></property>
</bean>
测试结果:
注:set注入的方式可以存在type类型用于定位给哪个属性赋值,但是必须写全限定类名,如下name="teacherName"属性的赋值:
<bean id="teacher" class="org.dsl.entity.Teacher">
<property name="teacherName" value="zhangsan" type="java.lang.String"></property>
<property name="teacherAge" value="20"></property>
</bean>
- 利用构造器注入
实体类:
//Teacher实体类
public class Teacher {
private String teacherName;
private int teacherAge;
public Teacher() {
}
//此处为构造方法
public Teacher(String teacherName, int teacherAge) {
System.out.println("调用构造方法");
this.teacherName = teacherName;
this.teacherAge = teacherAge;
}
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
System.out.println("调用set方法");
this.teacherName = teacherName;
}
public int getTeacherAge() {
return teacherAge;
}
public void setTeacherAge(int teacherAge) {
this.teacherAge = teacherAge;
}
public void show() {
System.out.println("name:"+this.teacherName+"--age:"+this.teacherAge);
}
}
---------------------------------------------------------
//Course实体类
public class Course {
private String courseName;
private int courseHour;
private Teacher teacher;
public Course() {
}
public Course(String courseName, int courseHour, Teacher teacher) {
System.out.println("调用Course构造方法");
this.courseName = courseName;
this.courseHour = courseHour;
this.teacher = teacher;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public int getCourseHour() {
return courseHour;
}
public void setCourseHour(int courseHour) {
this.courseHour = courseHour;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public void show() {
System.out.println("courseName:"+this.courseName+"--courseHour:"+this.getCourseHour()+
"--TeacherName:"+this.getTeacher().getTeacherName()+"--TeacherAge:"+this.getTeacher().getTeacherAge());
}
}
applicationContext.xml文件中的配置:
<bean id="teacher" class="org.dsl.entity.Teacher">
<constructor-arg value="20" type="int" index="1" name="teacherAge"></constructor-arg>
<constructor-arg value="lisi" type="String" index="0" name="teacherName"></constructor-arg>
</bean>
<bean id="course" class="org.dsl.entity.Course">
<constructor-arg value="shuxue"></constructor-arg>
<constructor-arg value="200"></constructor-arg>
<constructor-arg ref="teacher"></constructor-arg>
</bean>
注:引用复杂类型使用ref,例如( ref=“teacher”),当构造器中的value不能够确定某个属性时,可以利用type(属性类型)、index(属性顺序)、name(属性名称)三者中的一种或多种,用来定位某个属性,具体如下图所示:
测试结果:
- 利用P命名空间注入
- 如果安装STS工具,可进行如下操作,将P命名空间引入,如下图所示:
如上操作完成后,applicationContext.xml中的约束新增如下语句:
- 如果没有安装STS工具,可以直接将下述语句copy上去即可。
xmlns:p=“http://www.springframework.org/schema/p”
- 如果安装STS工具,可进行如下操作,将P命名空间引入,如下图所示:
- applicationContext.xml文件中的配置:
<bean id="teacher" class="org.dsl.entity.Teacher">
<constructor-arg value="20" type="int" index="1" name="teacherAge"></constructor-arg>
<constructor-arg value="lisi" type="String" index="0" name="teacherName"></constructor-arg>
</bean>
<bean id="course" class="org.dsl.entity.Course" p:courseHour="200" p:courseName="Tianwen" p:teacher-ref="teacher">
</bean>
如图所示:
- 测试结果:
注:在进行属性赋值时可以有两种方式: - property内部赋值:具体的值必须使用双引号“”
<bean id="teacher" class="org.dsl.entity.Teacher">
<property name="teacherName" value="zhangsan" type="java.lang.String"></property>
<property name="teacherAge" value="20"></property>
</bean>
- property外部赋值:不使用双引号“”
<bean id="teacher" class="org.dsl.entity.Teacher">
<property name="teacherName"> <value>zhangsan</value> </property>
<property name="teacherAge" > <value>20</value> </property>
</bean>
- 当赋空值时参考如下:
<bean id="teacher" class="org.dsl.entity.Teacher">
<property name="teacherName"> <value></value> </property>
<property name="teacherAge" > <value></value> </property>
</bean>
<bean id="teacher" class="org.dsl.entity.Teacher">
<property name="teacherName" value=""> </property>
<property name="teacherAge" value=""> </property>
</bean>
- 赋值为null时没有value
<bean id="teacher" class="org.dsl.entity.Teacher">
<property name="teacherName" > <null/> </property>
<property name="teacherAge" > <null/> </property>
</bean>
复杂类型赋值
- applicationContext.xml中的配置:
<bean id="collection" class="org.dsl.entity.CollectionDemo">
<property name="listElement">
<list>
<value>足球</value>
<value>篮球</value>
</list>
</property>
<property name="mapElement">
<map>
<entry>
<key>
<value>foot</value>
</key>
<value>足球</value>
</entry>
<entry>
<key>
<value>lanqiu</value>
</key>
<value>篮球</value>
</entry>
</map>
</property>
<property name="array">
<array>
<value>足球</value>
<value>篮球</value>
</array>
</property>
<property name="setElement">
<set>
<value>足球</value>
<value>篮球</value>
</set>
</property>
<property name="popElement">
<props>
<prop key="foot">足球</prop>
<prop key="basketboll">篮球</prop>
</props>
</property>
</bean>
- 实体类
package org.dsl.entity;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class CollectionDemo {
private java.util.List<String> listElement;
private Set<String> setElement;
private Map<String, Object> mapElement;
private String [] array;
private Properties popElement;
public java.util.List<String> getListElement() {
return listElement;
}
public void setListElement(java.util.List<String> listElement) {
this.listElement = listElement;
}
public Set<String> getSetElement() {
return setElement;
}
public void setSetElement(Set<String> setElement) {
this.setElement = setElement;
}
public Map<String, Object> getMapElement() {
return mapElement;
}
public void setMapElement(Map<String, Object> mapElement) {
this.mapElement = mapElement;
}
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
public Properties getPopElement() {
return popElement;
}
public void setPopElement(Properties popElement) {
this.popElement = popElement;
}
public void show() {
String strContext = "";
for (String str : array) {
strContext+=str+",";
}
System.out.println("listElement:"+this.listElement+"\nsetElement:"
+this.setElement+"\nmapElement:"+this.mapElement+"\narray:"+strContext+"\npopElement:"+this.popElement);
}
}
- 测试代码
package org.dsl.test;
import org.dsl.entity.CollectionDemo;
import org.dsl.entity.Course;
import org.dsl.entity.Teacher;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Course course = (Course)context.getBean("course");
course.show();
}
}
- 测试结果
注:集中复杂类型在applicationContext.xml中的赋值可以相互利用,也不会报错且运行正常,但是最好还是按照响应的类型去匹配使用。
- 相互使用,即数组中使用List进行赋值,List中用Set赋值,皆不会报错。
- 正常使用,即按照相应类型使用,数组用array,List使用List,map使用map等。
特殊类型的装配(只适用Bean中存在引用类型)
- 利用autowire属性进行装配,该属性值包括byName(根据Id名称进行装配)、byType(根据类型进行装配)、constructor(根据构造器进行装配)、default(默认自动选择装配方式)、no(不进行自动装配)
- applicationContext.xml文件样式:
<bean id="teacher" class="org.dsl.entity.Teacher">
<property name="teacherName" value="zhangsan"></property>
<property name="teacherAge" value="20" ></property>
</bean>
<bean id="course" class="org.dsl.entity.Course" autowire="byName">
<property name="courseName" value="shuxue"></property>
<property name="courseHour" value="2"></property>
<property name="teacher" ref="teacher"></property>
</bean>
默认全局自动装配
- 在applicationContext.xml文件的约束处,进行全局的默认自动装配设置,其中byName属性可替换为byType(根据类型进行装配)、constructor(根据构造器进行装配)、default(默认自动选择装配方式)、no(不进行自动装配)
利用注解的方式进行装配
- 进行如下扫描器配置,来查询相应包下的注解,利用相应注解,将属性装配到IOC容器中
- 在applicationContext.xml中配置扫描器,如有多个包要扫描,可以进行逗号分隔。
- 在相应代码层面利用注解进行注册
其中@Component(“teacherDao”)等价于
如果存在引用类型例如图片中的StudentDao属性的注入,存在两种方式:
第一种:利用@Autowired(自动装配)来实现,实际工作原理是在springIOC容器中,按照类型为StudentDao的bean进行查找匹配的;
第二种:利用@Autowired+@Qualifier(“bean中的属性名:id”),来实现按照springIOC中的属性Id,进行查找匹配的。
注:Component是较为通用的注解,但是在代码可读性和明确性方面,通常使用@Repository–对应存储层;@Service–对应业务层;@Controller–对应控制层。