IOC:Inverse Of Controller,控制反转

  • 反转了依赖关系的满足方式,由之前的自己创建依赖对象,变为由工厂推送,(由主动创建变为被动获取,即所谓的反转),解决了具有依赖关系的组件之间的强耦合

DI:依赖注入

依赖注入:在Spring创建对象的同时,为其属性赋值,称之为依赖注入。 依赖注入的三种方式:

  1. Set注入
  2. 构造方法注入
  3. 自动查找

在Spring XML配置中,只有一种声明bean的方式,即使用 <bean> 标签并指定 class 属性

属性注入 - 图1

Set注入

创建对象时,Spring工厂会通过Set方法为对象的属性赋值

使用set注入有两种方法:
1、使用<property>标签

bean标签指定创建一个实例,property指使用set方法对相应的属性进行注入:

注入类型 实现
注入直接量 使用<value>标签,特殊字符需要转义
引用bean 使用<ref>标签实现,注意 bean 属性和 local 属性的区别
使用内部bean 使用<property name="inner"><bean class="内部类路径"/></property>
注入集合类型的属性 分别使用<list><set><map><props>标签实现
注入null和空字符串值 使用<null/>注入null值,使用<value></value>注入空字符串

2、使用 p- 命名空间:p- 命名空间是 bean 的一个属性,使用

  1. <beans> 标签中引入 xmlns:p="http://www.springframework.org/schema/p" 命名空间
  2. 基本语法:p:属性名称[-ref]="属性值"
    属性名称可以使用 arg0,... 或者具体的属性名
  3. p-命名空间无法直接导入集合,需要使用 utils 工具

使用<property>标签

1、创建一个目标 Bean 类型:

  1. // Address实体
  2. @Data
  3. @AllArgsConstructor
  4. public class Address {
  5. private String name;
  6. private Integer passport;
  7. }
  8. // User实体
  9. @Data
  10. public class User {
  11. private Integer id;
  12. private String name;
  13. private Date birthday;
  14. private String[] hobbies;
  15. private Set<String> phone;
  16. private List<String> friends;
  17. private Map<String,Integer> scores;
  18. private Properties files;
  19. // 自建对象
  20. private Address address;
  21. private Map<Integer,Address> map;
  22. // 内部bean
  23. private InnerClass inner;
  24. @Data
  25. private static class InnerClass{
  26. private String name;
  27. }
  28. }

2、配置spring-context.xml文件:

  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. https://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!-- bean对象配置 -->
  7. <bean id="address" class="top.songfang.entity.Address">
  8. <constructor-arg name="name" value="北京"/>
  9. <constructor-arg name="passport" value="18"/>
  10. </bean>
  11. <bean id="address1" class="top.songfang.entity.Address">
  12. <constructor-arg name="name" value="上海"/>
  13. <constructor-arg name="passport" value="20"/>
  14. </bean>
  15. <bean id="user" class="top.songfang.entity.User">
  16. <!-- set方法注入 -->
  17. <!-- 简单数据类型注入 -->
  18. <property name="id" value="1"/>
  19. <property name="name" value="张"/>
  20. <property name="birthday" value="2002/12/23 12:20:30"/>
  21. <!-- 复杂属性注入 -->
  22. <!-- 数组注入 -->
  23. <property name="hobbies">
  24. <array>
  25. <value>篮球</value>
  26. <value>足球</value>
  27. <value>排球</value>
  28. </array>
  29. </property>
  30. <!-- List注入 -->
  31. <property name="phone">
  32. <list>
  33. <value>135468</value>
  34. <value>135588</value>
  35. </list>
  36. </property>
  37. <!-- set注入-->
  38. <property name="friends">
  39. <set>
  40. <value>扎根</value>
  41. <value>木哦</value>
  42. </set>
  43. </property>
  44. <!-- map注入 -->
  45. <property name="scores">
  46. <map>
  47. <entry key="数学" value="78"/>
  48. <entry key="英语" value="88"/>
  49. </map>
  50. </property>
  51. <!-- properties -->
  52. <property name="files">
  53. <props>
  54. <prop key="英语">98</prop>
  55. <prop key="数学">77</prop>
  56. </props>
  57. </property>
  58. <!-- 自建对象 -->
  59. <property name="address" ref="address"/>
  60. <!-- map+自建对象 -->
  61. <property name="map">
  62. <map>
  63. <entry key="1" value-ref="address"/>
  64. <entry key="2" value-ref="address1"/>
  65. </map>
  66. </property>
  67. <!-- 内部类注入 -->
  68. <property name="inner">
  69. <bean class="top.songfang.entity.User.InnerClass">
  70. <property name="name" value="内部类属性"/>
  71. </bean>
  72. </property>
  73. </bean>
  74. </beans>

**

使用 p- 命名空间

1、引入 p- 命名空间:在beans标签中新增xmlns:p="http://www.springframework.org/schema/p"

2、单靠 p- 命名空间无法实现集合属性的注入,因此如果需要使用 p- 命名空间注入集合属性,需要使用 util 工具,使用方法:

  • <beans> 中引入 utils :

    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. xmlns:p="http://www.springframework.org/schema/p"
    5. xmlns:util="http://www.springframework.org/schema/util"
    6. xsi:schemaLocation="http://www.springframework.org/schema/beans
    7. https://www.springframework.org/schema/beans/spring-beans.xsd
    8. http://www.springframework.org/schema/util
    9. https://www.springframework.org/schema/util/spring-util.xsd">
    10. </beans>
  • 使用 utils 标签定义list、set、map等,再使用 p:xx-ref=”” 进行引入

元素 描述
<util:constant> 引用某个类型的 public static域,并将其暴露为bean
<util:list> 创建一个 java.util.List类型的bean,其中包含值或引用
<util:map> 创建一个 java.util.Map类型的bean,其中包含值或引用
<util:properties> 创建一个 java.util.Properties类型的bean
<util:property-path> 引用一个 bean的属性(或内嵌属性),并将其暴露为bean
<util:set> 创建一个 java.util.Set类型的bean,其中包含值或引用

3、使用示例:

  1. <util:list id="hobbies">
  2. <value>篮球</value>
  3. <value>足球</value>
  4. </util:list>
  5. <bean id="user" class="top.songfang.entity.User"
  6. p:id="10"
  7. p:name="zhan"
  8. p:hobbies-ref="hobbies"/>


构造函数注入

在XML中使用构造器注入时,有两种基本的配置方案:

1、<constructor-arg>元素:
注意事项:

  1. 构造参数存个数不一样时,通过控制<constructor-arg>标签的数量进行区分
  2. 构造参数个数一致时,通过在标签中引入 type 属性,进行类型的区分<constructor-arg type="java.lang.String">

对上述User对象进行使用<constructor-arg>元素注入:

  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. https://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!-- bean对象配置 -->
  7. <bean id="address" class="top.songfang.entity.Address">
  8. <constructor-arg name="name" value="北京"/>
  9. <constructor-arg name="passport" value="18"/>
  10. </bean>
  11. <bean id="address1" class="top.songfang.entity.Address">
  12. <constructor-arg name="name" value="上海"/>
  13. <constructor-arg name="passport" value="20"/>
  14. </bean>
  15. <bean id="user" class="top.songfang.entity.User">
  16. <!-- 简单元素构造器注入 -->
  17. <constructor-arg name="id" value="18"/>
  18. <constructor-arg name="name" value="中"/>
  19. <constructor-arg name="birthday" value="2002/12/23 12:20:30"/>
  20. <!-- 复杂元素构造器注入 -->
  21. <!-- 数组注入 -->
  22. <constructor-arg name="hobbies">
  23. <array>
  24. <value>篮球</value>
  25. <value>足球</value>
  26. <value>排球</value>
  27. </array>
  28. </constructor-arg>
  29. <!-- List注入 -->
  30. <constructor-arg name="phone">
  31. <list>
  32. <value>135468</value>
  33. <value>135588</value>
  34. </list>
  35. </constructor-arg>
  36. <!-- set注入-->
  37. <constructor-arg name="friends">
  38. <set>
  39. <value>扎根</value>
  40. <value>木哦</value>
  41. </set>
  42. </constructor-arg>
  43. <!-- map注入 -->
  44. <constructor-arg name="scores">
  45. <map>
  46. <entry key="数学" value="78"/>
  47. <entry key="英语" value="88"/>
  48. </map>
  49. </constructor-arg>
  50. <!-- properties -->
  51. <constructor-arg name="files">
  52. <props>
  53. <prop key="英语">98</prop>
  54. <prop key="数学">77</prop>
  55. </props>
  56. </constructor-arg>
  57. <!-- 自建对象 -->
  58. <constructor-arg name="address" ref="address"/>
  59. <!-- map+自建对象 -->
  60. <constructor-arg name="map">
  61. <map>
  62. <entry key="1" value-ref="address"/>
  63. <entry key="2" value-ref="address1"/>
  64. </map>
  65. </constructor-arg>
  66. </bean>
  67. </beans>

**
2、使用 c- 命名空间,c- 命令空间是<bean> 元素的一个属性:

  1. 引入 c- 命名空间:在<beans>标签中新增 xmlns:c="http://www.springframework.org/schema/c"
  2. 使用:
    1. <!-- c:构造器参数名[-ref]="要注入的bean" -->
    2. <bean id="address1" class="top.songfang.entity.Address"
    3. c:name="上海"
    4. c:passport="20"/>
    注意事项:
  • 参数名其他写法:

    • _n:n为参数,指参数在构造方法中的位置
    • _:在构造方法只有一个参数时,可以不用标识参数
      1. <bean id="address1" class="top.songfang.entity.Address" c:_="上海"/>
  • c- 命名空间不支持集合的注入,如果需要注入集合需要使用 util 工具

自动化装配 bean

Spring从两个角度来实现自动化装配:

  • 组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean
  • 自动装配(autowiring):Spring自动满足bean之间的依赖

在spring-context.xml中开启组件扫描:<context:component-scan base-package="包名"/>
bean标签中有一个 autowire 属性,支持通过 type 和 name 的自动注入