动力节点Spring框架学习笔记-王鹤(一)IOC控制反转

2022-01-12 15:48:53 浏览数 (1)

  • 官方下载地址

动力节点spring资料

  • 视频观看地址

https://www.bilibili.com/video/BV1nz4y1d7uy

一、IOC控制反转

1.1 概述

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

IoC 是一个概念,是一种思想,其实现方式多种多样。当前是依赖注入。应用广泛

依赖:classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA对 classB 有依赖。

1.2 IOC的实现

依赖注入:DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行完成。

依赖注入 DI 是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。

Spring 的依赖注入对调用者与被调用者几乎没有任何要求,完全支持对象之间依赖关系的管理。

Spring 容器是一个大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称为 Bean。

Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”的方式来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。

1.3 关于bean标签

  • bean标签的配置
代码语言:javascript复制
    <!--告诉spring创建对象
        声明bean , 就是告诉spring要创建某个类的对象
        id:对象的自定义名称,唯一值。 spring通过这个名称找到对象
        class:类的全限定名称(不能是接口,因为spring是反射机制创建对象,必须使用类)

        spring就完成 SomeService someService = new SomeServiceImpl();
        spring是把创建好的对象放入到map中, spring框架有一个map存放对象的。
           springMap.put(id的值, 对象);
           例如 springMap.put("someService", new SomeServiceImpl());

        一个bean标签声明一个对象。
    -->
    <bean id="someService" class="com.jjh.service.impl.SomeServiceImpl" />
    <bean id="someService1" class="com.jjh.service.impl.SomeServiceImpl" scope="prototype"/>
  • 测试类(1)使用
代码语言:javascript复制
@Test
    public void test01(){
        SomeService service  = new SomeServiceImpl();
        service.doSome();
   }
  • 测试类(2)使用
代码语言:javascript复制
@Test
    public void test03(){
        String config="beans.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //使用spring提供的方法, 获取容器中定义的对象的数量
        int nums  = ac.getBeanDefinitionCount();
        System.out.println("容器中定义的对象数量:" nums);
        //容器中每个定义的对象的名称
        String names [] = ac.getBeanDefinitionNames();
        for(String name:names){
            System.out.println(name);
        }
    }

1.4 基于XML的DI

1.4.1 set注入(重点)

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

代码语言:javascript复制
 <?xml version="1.0" encoding="UTF-8"?>
<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">

    <!--声明student对象
        注入:就是赋值的意思
        简单类型: spring中规定java的基本数据类型和String都是简单类型。
        di:给属性赋值
        1. set注入(设值注入) :spring调用类的set方法, 你可以在set方法中完成属性赋值
         1)简单类型的set注入
            <bean id="xx" class="yyy">
               <property name="属性名字" value="此属性的值"/>
               一个property只能给一个属性赋值
               <property....>
            </bean>
            
         2) 引用类型的set注入 : spring调用类的set方法
           <bean id="xxx" class="yyy">
              <property name="属性名称" ref="bean的id(对象的名称)" />
           </bean>
    -->
    <bean id="myStudent" class="com.jjh.ba02.Student" >
        <property name="name" value="李四" />
        <property name="age" value="26" />
        <!--引用类型-->
        <property name="school" ref="mySchool" /><!--setSchool(mySchool)-->
    </bean>
    
    <!--声明School对象-->
    <bean id="mySchool" class="com.jjh.ba02.School">
        <property name="name" value="北京大学"/>
        <property name="address" value="北京的海淀区" />
    </bean>
</beans>

1.4.2 构造注入

构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。即使用构造器设置依赖关系。

代码语言:javascript复制
<!--
        2.构造注入:spring调用类有参数构造方法,在创建对象的同时,在构造方法中给属性赋值。
          构造注入使用 <constructor-arg> 标签
          <constructor-arg> 标签:一个<constructor-arg>表示构造方法一个参数。
          <constructor-arg> 标签属性:
             name:表示构造方法的形参名
             index:表示构造方法的参数的位置,参数从左往右位置是 0 , 1 ,2的顺序
             value:构造方法的形参类型是简单类型的,使用value
             ref:构造方法的形参类型是引用类型的,使用ref
    -->
            <!--使用name属性实现构造注入-->
            <bean id="myStudent" class="com.jjh.ba03.Student" >
                <constructor-arg name="myage" value="20" />
                <constructor-arg name="mySchool" ref="myXueXiao" />
                <constructor-arg name="myname" value="周良"/>
            </bean>
        
            <!--使用index属性-->
            <bean id="myStudent2" class="com.jjh.ba03.Student">
                <constructor-arg index="1" value="22" />
                <constructor-arg index="0" value="李四" />
                <constructor-arg index="2" ref="myXueXiao" />
            </bean>
        
            <!--省略index-->
            <bean id="myStudent3" class="com.jjh.ba03.Student">
                <constructor-arg  value="张强强" />
                <constructor-arg  value="22" />
                <constructor-arg  ref="myXueXiao" />
            </bean>

1.4.3 引用类型自动注入

  • byName(按名称注入)

java类中引用类型的属性名和spring容器中(配置文件)<bean>的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型。

代码语言:javascript复制
<!--
        语法:
         <bean id="xx" class="yyy" autowire="byName">
            简单类型属性赋值
         </bean>
         -->
         
    <bean id="myStudent" class="com.jjh.ba04.Student" autowire="byName">
        <property name="name" value="李四" />
        <property name="age" value="26" />
        <!--引用类型-->
        <!--<property name="school" ref="mySchool" />-->
    </bean>

    <!--声明School对象-->
    <bean id="school" class="com.jjh.ba04.School">
        <property name="name" value="清华大学"/>
        <property name="address" value="北京的海淀区" />
    </bean>
  • byType(按类型注入)

java类中引用类型的数据类型和spring容器中(配置文件)的class属性是同源关系的,这样的bean能够赋值给引用类型

代码语言:javascript复制
<!--
        语法:
         <bean id="xx" class="yyy" autowire="byType">
            简单类型属性赋值
         </bean>

         注意:在byType中, 在xml配置文件中声明bean只能有一个符合条件的,
              多余一个是错误的
-->
    <!--byType-->
    <bean id="myStudent" class="com.jjh.ba05.Student" autowire="byType">
        <property name="name" value="张飒" />
        <property name="age" value="26" />
        <!--引用类型-->
        <!--<property name="school" ref="mySchool" />-->
    </bean>

    <!--声明School对象-->
    <bean id="mySchool" class="com.jjh.ba05.School">
        <property name="name" value="人民大学"/>
        <property name="address" value="北京的海淀区" />
    </bean>

1.4.4 具有关联关系的配置

代码语言:javascript复制
student类的配置文件
        <!--student 模块bean声明-->
    <bean id="myStudent" class="com.jjh.domain.entity.Student" autowire="byType">
        <property name="name" value="张三"/>
        <property name="age" value="23"/>
        <!--引用类型数据-->
    </bean>
  • School类的配置文件
代码语言:javascript复制
    <bean id="mySchool" class="com.jjh.domain.entity.School">
        <property name="address" value="松潘"/>
        <property name="name" value="工大"/>
    </bean>
  • total配置文件
代码语言:javascript复制
    <!--
         包含关系的配置文件:
         spring-total表示主配置文件 : 包含其他的配置文件的,主配置文件一般是不定义对象的。
         语法:<import resource="其他配置文件的路径" />
         关键字:"classpath:" 表示类路径(class文件所在的目录),
               在spring的配置文件中要指定其他文件的位置, 需要使用classpath,告诉spring到哪去加载读取文件。
    -->

    <!--加载的是文件列表-->
    <!--
    <import resource="classpath:ba01/applicationContext01.xml" />
    <import resource="classpath:ba01/applicationContext02.xml" />
    -->

    <!--
       在包含关系的配置文件中,可以通配符(*:表示任意字符)
       注意: 主的配置文件名称不能包含在通配符的范围内(不能叫做spring-total.xml)
    -->
    <!--导入配置文件-->
    <import resource="classpath:ba01/applicationContext*"/>

1.5 基于注解的DI

  • 注解配置的约束文件
代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">

<!--spring 创建容器时要扫描的包  @ComponentScan --> 
<context:component-scan base-package="com.jjh">
</context:component-scan>
</beans>
  • 实体类
代码语言:javascript复制
@Data
@Component("myStudent")
public class Student {
    private String name;
    private int age;
    //引用类型
    private School school;
    }
  • 测试类中调用
代码语言:javascript复制
  @Test
    public void demo01(){
        String config = "applicationContext.xml";
        ApplicationContext app = new ClassPathXmlApplicationContext(config);
        Student myStudent = (Student)app.getBean("myStudent");
        System.out.println(myStudent);
    }

1.5.1 使用注解的步骤

1. 加入maven的依赖 spring-context,在你加入spring-context的同时, 间接加入spring-aop的依赖。使用注解必须使用spring-aop依赖

2. 在类中加入spring的注解(多个不同功能的注解)

3. 在spring的配置文件中,加入一个component-scan组件扫描器的标签,说明注解在你的项目中的位置

代码语言:javascript复制
<!--声明组件扫描器(component-scan),组件就是java对象
        base-package:指定注解在你的项目中的包名。
        component-scan工作方式: spring会扫描遍历base-package指定的包,
           把包中和子包中的所有类,找到类中的注解,按照注解的功能创建对象,或给属性赋值。

       加入了component-scan标签,配置文件的变化:
        1.加入一个新的约束文件spring-context.xsd
        2.给这个新的约束文件起个命名空间的名称
    -->
    <context:component-scan base-package="com.jjh.ba01" />

1.5.2 多注解项目分层

1. @Component: 创建对象的, 等同于<bean>的功能

属性:value 就是对象的名称,也就是bean的id值,value的值是唯一的,创建的对象在整个spring容器中就一个

2. @Repository(用在持久层类的上面) : 放在dao的实现类上面,表示创建dao对象,dao对象是能访问数据库的。

3. @Service(用在业务层类的上面):放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务等功能的。

4. @Controller(用在控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求的处理结果

以上三个注解的使用语法和@Component一样的。 都能创建对象,但是这三个注解还有额外的功能。

1.5.3 简单类型的赋值

@Value: 简单类型的属性赋值

属性: value 是String类型的,表示简单类型的属性值

使用位置:1.在属性定义的上面,无需set方法,推荐使用。      2.在set方法的上面

  • 配置文件
代码语言:javascript复制
<context:component-scan base-package="com.jjh"/>
    <!--配置属性的properties文件-->
    <context:property-placeholder location="classpath:student.properties"/>
  • properties文件
代码语言:javascript复制
name=Dick
age=20
代码语言:javascript复制
@Component("myStudent")
public class Student {

    //@Value("李四" )
    @Value("${myname}") //使用属性配置文件中的数据
    private String name;

    @Value("${myage}")  //使用属性配置文件中的数据
    private Integer age;
    }

1.5.4 引用类型的赋值

  • 默认方式

1.@Autowired: spring框架提供的注解,实现引用类型的赋值

2.spring中通过注解给引用类型赋值,使用的是自动注入原理 ,支持byName, byType

3.@Autowired:默认使用的是byType自动注入

4.使用位置:

  • 在属性上面使用

在set方法上面使用

代码语言:javascript复制
@Component("myStudent")
public class Student {

    @Value("李四" )
    private String name;
    @Value("20")
    private Integer age;

    @Autowired
    private School school;
    }
  • 通过名称赋值

如果要使用byName方式:

在属性上面加入@Autowired

属性上面加入@Qualifier(value="bean的id") :表示使用指定名称的bean完成赋值在

代码语言:javascript复制
@Component("myStudent")
public class Student {

    @Value("李四" )
    private String name;
    @Value("20")
    private Integer age;

    @Autowired
    @Qualifier("mySchool")
    private School school;
    }

1.5.5 Autowired的required属性

  • required :是一个boolean类型的,默认true
  • required=true:表示引用类型赋值失败,程序报错,并终止执行
  • required=false:引用类型如果赋值失败, 程序正常执行,引用类型是null

1.5.6 JDK注解@Resource自动注入

1.@Resource: 来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值

2.使用的也是自动注入原理,支持byName,byType默认是byName

3.使用位置:

  • 在属性定义的上面,无需set方法,推荐使用
  • 在set方法的上面

4.默认是byName:先使用byName自动注入,如果byName赋值失败,再使用byType

5.@Resource只使用byName方式,需要增加一个属性 name,name的值是bean的id(名称)

  • 指定name
代码语言:javascript复制
@Component("myStudent")
public class Student {

    @Value("李四" )
    private String name;
    private Integer age;

    //只使用byName
    @Resource(name = "mySchool")
    private School school;
  • 默认配置
代码语言:javascript复制
@Component("myStudent")
public class Student {

    @Value("李四" )
    private String name;
    private Integer age;

    //只使用byName
    @Resource
    private School school;

0 人点赞