Spring Framework学习之DI——依赖注入

怼烎@ 2022-01-14 14:49 385阅读 0赞

目录

  • setter注入
      • 注入匿名内部bean
      • 注入集合类型属性
      • 注入null、空字符串类型属性值
      • 注入复合属性值
          • 两个关联的java类
          • xml配置注入复合属性
          • 获取注入复合属性的属性值
      • 注入外部properties文件中的属性值
          • jdbc.properties
          • xml配置引入外部的properties文件
      • 通过p命名空间注入属性
          • 要想使用p命名空间,必须要加相应的p的schema
          • 通过p命名空间来注入属性
  • 构造方法注入
            • constructor-arg标签属性
      • 通过c命名空间注入构造参数
  • 自动装配
      • byName和byType方式
            • java bean类
            • xml配置
            • 程序运行入口
      • constructor方式
            • java bean类
            • xml配置
            • 程序运行入口
      • 将某个bean从自动装配候选中排除

Spring 依赖注入(DI Dependency Injection),可以自动帮我们解决类与类之间的各种依赖问题。通常公司中的项目都包含很多的类,而这些类与类之间都有各种依赖关系,比如:组合、聚合、依赖等。通过Spring的DI功能,结合IOC容器, 我们可以把这些复杂的关系交由Spring来管理, 我们在使用时,Spring会自动帮我们把依赖的对象注入进来,大大降低开发难度。
Spring中的依赖注入主要包含两种:通过构造方法中的注入和通过Setter方法注入

setter注入

注入匿名内部bean

内部bean不需要指定id、name属性,如果指定了也无法在外部直接获取,另外内部bean也不支持scope属性,因为内部bean始终是由外部bean创建的,并且只能在外部bean中使用

  1. <!-- 给Student注入一个匿名内部bean -->
  2. 第一种:
  3. <!-- setter注入 -->
  4. <bean id="student" class="com.lanou3g.spring.bean.Student">
  5. <property name="fruit">
  6. <bean class="com.lanou3g.spring.simple.Apple" >
  7. <property name="kind" value="CyanApple"
  8. </bean>
  9. </property>
  10. </bean>
  11. 第二种:
  12. <!-- 构造方法注入 -->
  13. <bean id="student" class="com.lanou3g.spring.bean.Student">
  14. <constructor-argname="fruit">
  15. <bean class="com.lanou3g.spring.simple.Apple" >
  16. <property name="kind" value="CyanApple"
  17. </bean>
  18. </property>
  19. </bean>

注入集合类型属性

  1. <!-- 注入集合、Map类型参数 -->
  2. <bean id="student" class="com.lanou3g.spring.bean.Student">
  3. <property name="hobbies">
  4. <list>
  5. <!-- 普通元素 -->
  6. <value>游泳</value>
  7. <value type="java.lang.Integer">0034</value>
  8. <!-- 引用类型元素 -->
  9. <ref bean="study" />
  10. </list>
  11. </property>
  12. <property name="gameTitles">
  13. <map>
  14. <entry key="LOL" value="嘴强王者"></entry>
  15. <entry key="王者农药" value="甩锅大神"></entry>
  16. <entry key="和平精英" value="菜鸡"></entry>
  17. </map>
  18. </property>
  19. </bean>

注入null、空字符串类型属性值

  1. <bean id="student" class="com.lanou3g.spring.bean.Student">
  2. <property name="age" value="" />
  3. </bean>
  4. <bean id="student" class="com.lanou3g.spring.bean.Student">
  5. <property name="age">
  6. <null />
  7. </property>
  8. </bean>

注入复合属性值

两个关联的java类
  1. @Setter
  2. @Getter
  3. public class People{
  4. private Student student;
  5. }
  6. @Setter
  7. @Getter
  8. public class Student{
  9. private Integer age;
  10. }
xml配置注入复合属性
  1. <bean id="people" class="com.lanou3g.spring.bean.People">
  2. <property name="student" ref="student" />
  3. <property name="student.age" value="23" />
  4. </bean>
  5. <bean id="student" class="com.lanou3g.spring.bean.Student" />
获取注入复合属性的属性值
  1. public static void main( String[] args ) {
  2. ApplicationContext cpxac = new AnnotationConfigApplicationContext(App.class);
  3. People people = cpxac.getBean(People.class);
  4. System.out.println(people.getStudent().getAge());
  5. }

注入外部properties文件中的属性值

jdbc.properties
  1. jdbc.driver.className=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql://localhost:3306/mydb
  3. jdbc.username=root
  4. jdbc.password=root
  5. jdbc.maxIdle=3
  6. jdbc.minIdle=1
  7. jdbc.maxActive=10
xml配置引入外部的properties文件
  1. <!-- 方式一 -->
  2. <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  3. <property name="location" value="classpath:jdbc.properties" />
  4. </bean>
  5. <!-- 方式二 -->
  6. <!-- 通过方式二这种方式和方式一等效,推荐使用 -->
  7. <context:property-placeholder location="classpath:jdbc.properties"/>
  8. <!-- 无论用方式一还是方式二都需配置下面的节点 -->
  9. <!-- 将外部properties文件中的属性注入到bean中 -->
  10. <bean id="jdbcConf" class="com.lanou3g.spring.bean.JDBCConf">
  11. <property name="url" value="${jdbc.url}" />
  12. <property name="driver" value="${jdbc.driver}" />
  13. <property name="userName" value="${jdbc.user}" />
  14. <property name="password" value="${jdbc.password}" />
  15. </bean>

通过p命名空间注入属性

要想使用p命名空间,必须要加相应的p的schema
  1. xmlns:p="http://www.springframework.org/schema/p"
通过p命名空间来注入属性
  1. <!--<bean id="yunjie1" class="com.lanou3g.spring.bean.Student">
  2. <property name="sname" value="张三" />
  3. </bean>-->
  4. <!-- 等效于上面的配置 -->
  5. <bean id="yunjie1" class="com.lanou3g.spring.bean.Student" p:sname="张三" />

构造方法注入

  1. package x.y;
  2. public class ThingOne {
  3. private int age;
  4. private String sname;
  5. private int gender;
  6. private ThingTwo thingTwo;
  7. public ThingOne(int age, ThingTwo thingTwo, String sname, int gender) {
  8. this.age = age;
  9. this.thingTwo = thingTwo;
  10. this.sname = sname;
  11. this.gender = gender;
  12. // ...
  13. }
  14. }
  15. public class ThingTwo {
  16. // ...
  17. }
  18. <beans>
  19. <!-- 有参注入 -->
  20. <bean id="beanOne" class="x.y.ThingOne">
  21. <!-- 通过此标签注入构造方法中的参数 -->
  22. <constructor-arg name="age" value="18" />
  23. <constructor-arg type="java.lang.String" value="张三" />
  24. <constructor-arg ref="beanTwo"/>
  25. </bean>
  26. <!-- 无参注入 -->
  27. <bean id="beanTwo" class="x.y.ThingTwo"/>
  28. </beans>
constructor-arg标签属性



































属性名 取值 含义
name 字符串 构造参数的名称
value 数值、字符串 构造参数的属性值,只适用于简单类型
type 类的全名 构造参数的类型,如果是简单类型,需要指定对应的封装类型
如果构造参数中有多个命中的类型,按照配置的先后顺序注入(可以通过配合index属性改变默认顺序)
index 数值 构造参数的位置,从0开始
ref 其他在Spring容器中配置的bean的name或者id 将容器中的其他bean作为构造参数注入

通过c命名空间注入构造参数

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:c="http://www.springframework.org/schema/c"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. https://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <bean id="beanTwo" class="x.y.ThingTwo"/>
  7. <bean id="beanThree" class="x.y.ThingThree"/>
  8. <!-- 传统方式注入构造参数 -->
  9. <bean id="beanOne" class="x.y.ThingOne">
  10. <constructor-arg name="thingTwo" ref="beanTwo"/>
  11. <constructor-arg name="thingThree" ref="beanThree"/>
  12. <constructor-arg name="email" value="something@somewhere.com"/>
  13. </bean>
  14. <!-- c命名空间方式注入构造参数 -->
  15. <bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
  16. c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>
  17. </beans>

自动装配

自动装配允许我们不用显示给某个bean注入依赖的属性或者构造参数,而交由Spring自动帮我们注入所需的依赖。

Spring给我们提供了以下四种选项


























自动装配模式 说明
no (默认值) 禁止Spring帮我们自动装配依赖,所有依赖由开发者显示注入。
byName 按照bean的名称注入。比如beanA有一个属性beanB需要注入,如果beanA配置了自动装配模式是byName,那么Spring会在容器中找bean的名称为beanB的bean,找到后自动帮我们注入到beanA中。如果没找到,则不会注入。
byType 按照bean的类型注入。byType模式需要保证容器中符合注入的类型的bean只有一个,如果匹配的类型有不止一个bean,那么会直接抛出运行时异常。如果没有一个匹配类型的bean,则不会注入。
constructor 类似于byType。但这种模式应用的对象是构造参数。如果构造参数需要注入参数类型的bean有不止一个,同样会抛出运行时异常。

byName和byType方式

java bean类
  1. @Setter
  2. @Getter
  3. public class People {
  4. private String pname;
  5. private Student student;
  6. }
  7. @Setter
  8. @Getter
  9. public class Student {
  10. private int age;
  11. }
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. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!-- 给Student类中的age属性赋值 -->
  7. <bean id="student" class="com.lanou3g.spring.bean.Student">
  8. <property name="age" value="25" />
  9. </bean>
  10. <!-- byName方式 -->
  11. <bean id="peopleByName" class="com.lanou3g.spring.bean.People"
  12. autowire="byName">
  13. <property name="pname" value="张三" />
  14. </bean>
  15. <!-- byType方式 -->
  16. <bean id="peopleByType" class="com.lanou3g.spring.bean.People"
  17. autowire="byType">
  18. <property name="pname" value="张三" />
  19. </bean>
  20. </beans>
程序运行入口
  1. public class App {
  2. public static void main( String[] args ) {
  3. ClassPathXmlApplicationContext cpxac = new ClassPathXmlApplicationContext("applicationContext.xml");
  4. cpxac.registerShutdownHook();
  5. // 按照名称自动注入属性
  6. People peopleByName= cpxac.getBean("peopleByName" , People.class);
  7. System.out.println("byName名字: " + peopleByName.getPname());
  8. System.out.println("byName学生年龄:" + peopleByName.getStudent().getAge());
  9. // 按照名称自动注入属性
  10. People peopleByType= cpxac.getBean("peopleByType" , People.class);
  11. System.out.println("byType名字: " + peopleByType.getPname());
  12. System.out.println("byType学生年龄:" + peopleByType.getStudent().getAge());
  13. }
  14. }

constructor方式

java bean类
  1. @Setter
  2. @Getter
  3. public class People {
  4. private String pname;
  5. private Student student;
  6. public People() {
  7. }
  8. public People(Student student) {
  9. this.student = student;
  10. }
  11. }
  12. @Setter
  13. @Getter
  14. public class Student {
  15. private int age;
  16. }
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. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!-- 给Student类中的age属性赋值 -->
  7. <bean id="student" class="com.lanou3g.spring.bean.Student">
  8. <property name="age" value="25" />
  9. </bean>
  10. <!-- byConstructor方式 -->
  11. <bean id="peopleByConstructor" class="com.lanou3g.spring.bean.People"
  12. autowire="constructor">
  13. <property name="pname" value="张三" />
  14. </bean>
  15. </beans>
程序运行入口
  1. public class App {
  2. public static void main( String[] args ) {
  3. ClassPathXmlApplicationContext cpxac = new ClassPathXmlApplicationContext("applicationContext.xml");
  4. cpxac.registerShutdownHook();
  5. // 按照名称自动注入属性
  6. People peopleByConstructor = cpxac.getBean("peopleByConstructor" , People.class);
  7. System.out.println("ByConstructor名字: " + peopleByConstructor.getPname());
  8. System.out.println("ByConstructor学生年龄:" + peopleByConstructor.getStudent().getAge());
  9. }
  10. }

将某个bean从自动装配候选中排除

我们可以通过给bean添加autowire-candidate属性,并且设置为false,从而让这个bean不参与自动装配(不会被自动装配到其他bean上)

发表评论

表情:
评论列表 (有 0 条评论,385人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SpringDI(依赖注入)

    依赖注入(DI)是一个过程,在这个过程中,对象仅通过构造函数参数、工厂方法的参数或在对象被实例化后通过属性设置来定义它们的依赖项(即与该对象一起工作的其他对象)。然后,容器在创

    相关 Spring---DI依赖注入

    上一篇介绍了关于IOC的内容:IOC称为控制反转,简单来说就是讲对象的创建的权利以及对象的生命周期的管理过程交给Spring容器来管理,从此在开发的过程中不需要关注对象的创建以

    相关 Spring依赖注入DI

    开头语:本文是我整理网上各种资料后整合而成的一篇文章。文中涉及到了代码重构、面向接口编程、持久化和工厂设计模式的内容。 1. Spring是什么?