• Spring——Spring核心(IoC)控制反转详细说明


    1. 控制反转描述

        控制反转IoC(Inversion of Control) 是一个概念,是一种思想。指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值, 依赖的管理。

        IoC 是一个概念,是一种思想,其实现方式多种多样。当前比较流行的实现方式是依赖注入。应用广泛。
    依赖:classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA对 classB 有依赖。

    Ioc 的实现:
        依赖注入:DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行完成
        依赖注入 DI 是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。

        Spring 的依赖注入对调用者与被调用者几乎没有任何要求,完全支持对象之间依赖关系的管理。Spring 框架使用依赖注入(DI)实现 IoC

        Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称为 Bean。Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”的方式来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。

    2. 创建Spring程序


    说明:本程序中需要了解的地方有:

    • 创建实体类中要有无参构造方法和setXXX()方法
    • 在xml文件中使用set注入简单类型的方法,创建对象
    • 测试类中ApplicationContext 用于加载 Spring 的配置文件,实现类使用的是ClassPathXmlApplicationContext,在容器启动之时,xml文件中所有的对象就会被全部创建

    2.1 创建Maven项目+配置文件

    Maven的配置地址

    配置好Maven的前提下创建Maven模块地址

    pom.xml配置
    添加spring的依赖,以及指定资源文件

    <dependencies>
        <dependency>
          <groupId>junitgroupId>
          <artifactId>junitartifactId>
          <version>4.11version>
          <scope>testscope>
        dependency>
        
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-contextartifactId>
          <version>5.2.5.RELEASEversion>
        dependency>
      dependencies>
    
      <build>
        <resources>
          <resource>
            <directory>/src/main/javadirectory>
            <includes>
              <include>**/*.xmlinclude>
              <include>**/*.propertiesinclude>
            includes>
          resource>
    
          <resource>
            <directory>/src/test/javadirectory>
            <includes>
              <include>**/*.xmlinclude>
              <include>**/*.propertiesinclude>
            includes>
          resource>
        resources>
      build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2.2 创建实体类

    • 使用spring容器创建对象的前提是实体类中需要有无参构造方法+setXXX()方法
    public class Student {
    
        private String name;
        private int age;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Student() {
            System.out.println("学生的无参构造方法被调用了......");
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.3 配置Spring的xml文件,使用Spring 容器创建对象

    • 这里就是一个Bean工厂,只要在这里配置bean标签,在容器启动的时候,对象就会被创建
    • 下面方式使用的是set注入的方式实现
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        
        <bean id="stu" class="com.lcl.pojo.Student">
            <property name="name" value="张三">property>
            <property name="age" value="21">property>
        bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.4 测试类

    • ApplicationContext 用于加载 Spring 的配置文件,在程序中充当“容器”的角色。其实现类使用的是ClassPathXmlApplicationContext
    • ApplicationContext 容器,会在容器对象初始化时,将其中的所有对象一次性全部装配好。以后代码中若要使用到这些对象,只需从内存中直接获取即可。执行效率较高。但占用内存。Spring初始化对象时要使用无参的构造方法,切记保证类中有无参构造方法。
    @Test
        public void testStudentSpring(){
            //有spring容器创建学生对象
            //如果想从spring容器中取出对象,则需要先创建容器对象,并且启动
            ApplicationContext ac = new ClassPathXmlApplicationContext("s01/applicationContext.xml");
            Student stu = (Student) ac.getBean("stu");
            System.out.println(stu);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3. 注入的分类

    3.1 set注入

    • set 注入也叫设值注入,通过 setter 方法传入被调用者的实例。这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用。

    3.1.1 简单类型的注入

    在这里插入图片描述

    在这里插入图片描述

    set注入简单类型的使用

     
        <bean id="school" class="com.lcl.pojo2.School">
            <property name="name" value="郑州大学">property>
            <property name="address" value="郑州市">property>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.1.2 引用类型的注入

    • set注入引用类型的使用:参数school属于引用类型【和实体类中属性名是一致的】,所以school属性值使用的是标签的ref属性
     
        <bean id="stu" class="com.lcl.pojo2.Student">
            <property name="name" value="李华">property>
            <property name="age" value="22">property>
            <property name="school" ref="school" >property>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.2 构造方法的注入

    3.2.1 使用构造方法参数名称注入

    • 这里同样使用Student类和School类,唯一不一样的就是这里在实体类中不再需要setXXX()方法
      
        <bean id="school" class="com.lcl.pojo3.School">
            <constructor-arg name="name" value="郑州大学">constructor-arg>
            <constructor-arg name="address" value="郑州市">constructor-arg>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.2.2 使用构造方法的参数索引下标注入

    • constructor-arg标签中的属性分别是:index,value
    
        <bean id="student" class="com.lcl.pojo3.Student">
            <constructor-arg index="0" value="李华">constructor-arg>
            <constructor-arg index="1" value="22">constructor-arg>
            <constructor-arg index="2" ref="school">constructor-arg>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.2.3 使用默认顺序注入

    • 这里的顺序要和实体类中的有参构造器的顺序一致,不然会报错
     
        <bean id="stu" class="com.lcl.pojo3.Student">
            <constructor-arg value="张三">constructor-arg>
            <constructor-arg value="22">constructor-arg>
            <constructor-arg ref="school">constructor-arg>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.4 注解注入

    • 依赖注入:DI(Dependency Injection),对于 DI 使用注解,将不再需要在 Spring 配置文件中声明bean 实例。Spring 中使用注解, 需要在原有 Spring 运行环境基础上再做一些改变。需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。

    • 基于注解的方式注入,创建对象和基于set注入的方式可以说成是换汤不换药

      • 药:创建对象并依赖注入
      • 汤:set注入的方式是在:xml文件中的bean标签创建 注解方式:通过注解注入值,只需要在xml文件中配置容器需要扫描的包即可【发现有相关注解就创建对象并注入值】
    • 使用注解注入的方式创建对象,在创建实体类的需要有无参构造方法

    3.4.1 注解类型

    创建对象的注解

    • @Component:可以创建任意对象.创建的对象的默认名称是类名的驼峰命名法.也可以指定对象的名称@Component(“指定名称”).
    • @Controller:专门用来创建控制器的对象(Servlet),这种对象可以接收用户的请求,可以返回处理结果给客户端.
    • @Service:专门用来创建业务逻辑层的对象,负责向下访问数据访问层,处理完毕后的结果返回给界面层.
    • @Repository:专门用来创建数据访问层的对象,负责数据库中的增删改查所有操作.

    依赖注入的注解

    说明:
        实际上没那么麻烦,是简单类型就是用Value,是引用类型就是用Autowired,其他的都是体会之后的了解内容

    • 简单类型(8种基本类型+String)的注入

      • @Value:用来给简单类型注入值
    • 引用类型的注入

      • A.@Autowired:使用类型注入值,从整个Bean工厂中搜索同源类型的对象进行注入.
        同源类型也可注入.
      • B.@Autowired
        @Qualifier(“名称”):使用名称注入值,从整个Bean工厂中搜索相同名称的对象进行注入.
        • 什么是同源类型:
          a.被注入的类型(Student中的school)与注入的类型是完全相同的类型
          b.被注入的类型(Student中的school父)与注入的类型(子)是父子类
          c.被注入的类型(Student中的school接口)与注入的类型(实现类)是接口和实现类的类型

      注意:在有父子类的情况下,使用按类型注入,就意味着有多个可注入的对象.此时按照名称进行二次筛选,选中与被注入对象相同名称的对象进行注入.

    3.4.2 注解类型的使用

    • 创建实体类对象,并且采用注解的方式创建对象,指明简单类型和因引用类型的属性值

    学校类

    @Component
    public class School {
    
        @Value("郑州大学")
        private String name;
        @Value("郑州市")
        private String address;
    
        public School() {
            System.out.println("School的无参构造方法被调用......");
        }
    
        @Override
        public String toString() {
            return "School{" +
                    "name='" + name + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    学生类

    @Component
    public class Student {
    
        @Value("李华")
        private String name;
        @Value("22")
        private int age;
    
       /* //引用类型
        @Autowired
        private School school;*/
    
        //引用类型按名称注入,
        //使用名称注入时需要子啊Qualifier注解中说明注入名
        //两个注解都不能少
        @Autowired
        @Qualifier("school")
        private School school;
    
        public Student() {
            System.out.println("Student的无参构造方法被调用了......");
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", school=" + school +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    xml文件中添加配置,spring容器需要扫描的包

    
    <context:component-scan base-package="com.lcl.s02">context:component-scan>
    
    • 1
    • 2

    测试:

      @Test
        public void testStudent(){
            ApplicationContext ac = new ClassPathXmlApplicationContext("s02/applicationContext.xml");
            Student student = (Student) ac.getBean("student");
            System.out.println(student);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    开发板通过网线连接电脑而上网
    实验七:数组、字符串(2)——字符串
    cpp层直接操作 surface
    jmeter使用监视器结果监控tomcat性能
    C++面试题和笔试题(三)
    RabbitMq优先级队列实现
    RISC-V架构 | 飞凌嵌入式FET7110-C国产高性能核心板现货发售!
    Python3+requests+unittest接口自动化测试
    外汇天眼:加拿大8月通胀率放缓幅度大于预期!加拿大10月份大幅加息可能性变小
    面向对象设计模式
  • 原文地址:https://blog.csdn.net/weixin_44606952/article/details/126645637