1. IOC(DI) - 控制反转(依赖注入)
所谓的IOC称之为控制反转,简单来说就是将对象的创建的权利及对象的生命周期的管理过程交由Spring框架来处理,从此在开发过程中不再需要关注对象的创建和生命周期的管理,而是在需要时由Spring框架提供,这个由spring框架管理对象创建和生命周期的机制称之为控制反转。而在 创建对象的过程中Spring可以依据配置对对象的属性进行设置,这个过称之为依赖注入,也即DI。
- 2. set方法注入
通常的javabean属性都会私有化,而对外暴露setXxx()getXxx()方法,此时spring可以通过这样的setXxx()方法将属性的值注入对象。
a. Spring内置的可直接注入类型的注入:
1 package cn.tedu.beans; 2 3 import java.util.List; 4 import java.util.Map; 5 import java.util.Properties; 6 import java.util.Set; 7 8 public class Hero { 9 private int id; 10 private String name; 11 private List<String> jobs; 12 private Set<String> set; 13 private Map<String,String> map; 14 private Properties prop; 15 16 public void setId(int id) { 17 this.id = id; 18 } 19 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 public void setJobs(List<String> jobs) { 25 this.jobs = jobs; 26 } 27 28 public void setSet(Set<String> set) { 29 this.set = set; 30 } 31 32 public void setMap(Map<String, String> map) { 33 this.map = map; 34 } 35 36 public void setProp(Properties prop) { 37 this.prop = prop; 38 } 39 40 @Override 41 public String toString() { 42 return "Hero [id=" + id + ", name=" + name + ", jobs=" + jobs 43 + ", set=" + set + ", map=" + map + ", prop=" + prop + "]"; 44 } 45 } 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd" 6 > 7 8 <bean id="hero" class="cn.tedu.beans.Hero"> 9 <property name="id" value="123"></property> 10 <property name="name" value="亚瑟 "></property> 11 <property name="jobs"> 12 <list> 13 <value>上单</value> 14 <value>打野</value> 15 <value>辅助</value> 16 <value>中单</value> 17 </list> 18 </property> 19 <property name="set"> 20 <set> 21 <value>aaa</value> 22 <value>bbb</value> 23 <value>ccc</value> 24 <value>aaa</value> 25 </set> 26 </property> 27 <property name="map"> 28 <map> 29 <entry key="addr" value="王者荣耀"></entry> 30 <entry key="addr" value="英雄联盟"></entry> 31 <entry key="skill" value="风火轮"></entry> 32 <entry key="age" value="19"></entry> 33 </map> 34 </property> 35 <property name="prop"> 36 <props> 37 <prop key="k1">v1</prop> 38 <prop key="k2">v2</prop> 39 <prop key="k3">v3</prop> 40 <prop key="k4">v4</prop> 41 </props> 42 </property> 43 </bean> 44 45 </beans>
测试
1 @Test 2 /** 3 * SpringDI set方式属性注入 - Spring内置的可直接注入类型的注入 4 */ 5 public void test1(){ 6 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 7 Hero hero = (Hero) context.getBean("hero"); 8 System.out.println(hero); 9 }
- b. 非Spring内置的可以直接注入类型的注入:
1 package cn.tedu.beans; 2 3 import java.util.List; 4 import java.util.Map; 5 import java.util.Properties; 6 import java.util.Set; 7 8 public class Hero { 9 private int id; 10 private String name; 11 private List<String> jobs; 12 private Set<String> set; 13 private Map<String,String> map; 14 private Properties prop; 15 private Dog dog; 16 private Cat cat; 17 18 19 public void setId(int id) { 20 this.id = id; 21 } 22 23 public void setName(String name) { 24 this.name = name; 25 } 26 27 public void setJobs(List<String> jobs) { 28 this.jobs = jobs; 29 } 30 31 public void setSet(Set<String> set) { 32 this.set = set; 33 } 34 35 public void setMap(Map<String, String> map) { 36 this.map = map; 37 } 38 39 public void setProp(Properties prop) { 40 this.prop = prop; 41 } 42 43 public void setDog(Dog dog) { 44 this.dog = dog; 45 } 46 47 public void setCat(Cat cat) { 48 this.cat = cat; 49 } 50 51 @Override 52 public String toString() { 53 return "Hero [id=" + id + ", name=" + name + ", jobs=" + jobs 54 + ", set=" + set + ", map=" + map + ", prop=" + prop + ", dog=" 55 + dog + ", cat=" + cat + "]"; 56 } 57 58 } 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd" 6 > 7 8 <bean id="hero" class="cn.tedu.beans.Hero"> 9 <property name="id" value="123"></property> 10 <property name="name" value="亚瑟 "></property> 11 <property name="jobs"> 12 <list> 13 <value>上单</value> 14 <value>打野</value> 15 <value>辅助</value> 16 <value>中单</value> 17 </list> 18 </property> 19 <property name="set"> 20 <set> 21 <value>aaa</value> 22 <value>bbb</value> 23 <value>ccc</value> 24 <value>aaa</value> 25 </set> 26 </property> 27 <property name="map"> 28 <map> 29 <entry key="addr" value="王者荣耀"></entry> 30 <entry key="addr" value="英雄联盟"></entry> 31 <entry key="skill" value="风火轮"></entry> 32 <entry key="age" value="19"></entry> 33 </map> 34 </property> 35 <property name="prop"> 36 <props> 37 <prop key="k1">v1</prop> 38 <prop key="k2">v2</prop> 39 <prop key="k3">v3</prop> 40 <prop key="k4">v4</prop> 41 </props> 42 </property> 43 <property name="dog" ref="dog"></property> 44 <property name="cat" ref="cat"></property> 45 </bean> 46 47 <bean id="dog" class="cn.tedu.beans.Dog"></bean> 48 <bean id="cat" class="cn.tedu.beans.Cat"></bean> 49 50 </beans>
测试:
1 @Test 2 /** 3 * SpringDI set方式属性注入 - 非Spring内置的可以直接注入类型的注入 4 */ 5 public void test2(){ 6 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 7 Hero hero = (Hero) context.getBean("hero"); 8 System.out.println(hero); 9 }
- 3. 基于构造方法的注入
对象属性设置的另一种方式是在对象创建的过程中通过构造方法传入并设置对象的属性。
spring也可以通过这样的构造方法实现属性的注入。
1 package cn.tedu.beans; 2 3 public class Student { 4 private int id; 5 private String name; 6 private Dog dog; 7 8 public Student(int id, String name, Dog dog) { 9 this.id = id; 10 this.name = name; 11 this.dog = dog; 12 } 13 14 @Override 15 public String toString() { 16 return "Student [id=" + id + ", name=" + name + ", dog=" + dog + "]"; 17 } 18 } 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd" 6 > 7 8 <bean id="student" class="cn.tedu.beans.Student"> 9 <!-- 10 index:为构造方法的第几个参数 进行配置 11 name:为构造方法的哪个名字的参数进行配置 12 **index 和 name 可以配置任何一个或同时配置 但要求一旦配置必须正确 13 **推荐优先使用index方式配置 防止没有源码造成name无法匹配到对应参数 14 type:该构造方法参数的类型 15 value:该构造方法参数的值 ,用来指定基本值 16 ref:该构造方法参数的值,用来指定引用其他bean的值 17 --> 18 <constructor-arg index="0" name="id" value="999"/> 19 <constructor-arg index="1" type="java.lang.String" value="张无忌"/> 20 <constructor-arg name="dog" ref="dog"/> 21 </bean> 22 23 <bean id="dog" class="cn.tedu.beans.Dog"></bean>
测试
</beans> 1 @Test 2 /** 3 * SpringDI 构造方法方式属性注入 4 */ 5 public void test3(){ 6 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 7 Student student = (Student) context.getBean("student"); 8 System.out.println(student); 9 }
- 4. 自动装配
在Spring的set方式实现的注入过程中,支持自动装配机制,所谓自动装配机制,会根据要设置的javabean属性的名字 或 类型 到spring中自动寻找对应id 或 类型的<bean>进行设置,从而 省去依次配置的过程,简化了配置。
为 指定<bean>开启自动装配:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd" 6 > 7 8 <!-- 9 autowire设定自动装配: 10 byName:根据javabean中需要注入的属性的名字 ,在spring容器中找对应id的<bean>将该<bean>的对象复制给 当前的属性 11 byType:根据javabean中需要注入的属性的类型,在spring容器中找对应class类型的<bean>将该<bean>的对象复制给 当前的属性 12 **byType方式 根据类型进行匹配,可能匹配到多个<bean>,此时会抛出异常。而byName是通过id来寻找<bean>,id没有重复,不会有这方面的问题,所以推荐使用byName方式 13 --> 14 <bean id="teacher" class="cn.tedu.beans.Teacher" autowire="byName"></bean> 15 <bean id="dog" class="cn.tedu.beans.Dog"></bean> 16 <bean id="cat" class="cn.tedu.beans.Cat"></bean> 17 18 </beans>
为全局配置自动装配:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd" 6 default-autowire="byName" 7 > 8 9 <!-- 10 autowire设定自动装配: 11 byName:根据javabean中需要注入的属性的名字 ,在spring容器中找对应id的<bean>将该<bean>的对象复制给 当前的属性 12 byType:根据javabean中需要注入的属性的类型,在spring容器中找对应class类型的<bean>将该<bean>的对象复制给 当前的属性 13 **byType方式 根据类型进行匹配,可能匹配到多个<bean>,此时会抛出异常。而byName是通过id来寻找<bean>,id没有重复,不会有这方面的问题,所以推荐使用byName方式 14 --> 15 <bean id="teacher" class="cn.tedu.beans.Teacher"></bean> 16 <bean id="dog" class="cn.tedu.beans.Dog"></bean> 17 <bean id="cat" class="cn.tedu.beans.Cat"></bean> 18 19 </beans> 1 package cn.tedu.beans; 2 3 public class Teacher { 4 private Dog dog; 5 private Cat cat; 6 public void setDog(Dog dog) { 7 this.dog = dog; 8 } 9 public void setCat(Cat cat) { 10 this.cat = cat; 11 } 12 13 @Override 14 public String toString() { 15 return "Teacher [dog=" + dog + ", cat=" + cat + "]"; 16 } 17 }
测试
1 @Test 2 /** 3 * SpringDI 自动装配 4 */ 5 public void test4(){ 6 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); 7 Teacher teacher = (Teacher) context.getBean("teacher"); 8 System.out.println(teacher); 9 }