第三章、容器:IoC

第三章、容器:IoC

1、是什么

1、是Inversion of Control的简写,译为“控制反转”,是一种设计思想,一个重要的面向对象编程法则

2、能知道我们如何设计松耦合,更牛的程序

3、Spring通过Ioc容器管理所有java对象的实例化和初始化,控制对象,和对象之间的依赖关系。

4、我们将由Ioc容器管理的java对象称为Spring Bean

5、它与使用关键字new创建的java对象没有任何区别

6、Ioc是Spring框架最重要的核心组件之一,贯穿Spring诞生和成长的过程

7、配置文件以XML、java注解或java代码实现

2、怎么用

1、理解

image-20231225161926104

1、控制反转(Ioc)

1、是一种思想

2、降低程序的耦合度,提高程序扩展能力

1、反转什么?

1、将对象的创建权利交给第三方容器负责

2、对象和对象之间关系的维护权,交给第三方容器负责

2、如何实现?

1、DI(Dependency injection):依赖注入

2、容器使用的map集合(方便,key-value)

3、图解

image-20231007173103481

2、依赖注入(DI)

1、 是什么?

1、DI(Dependency Injection):依赖注入,依赖注入实现了控制反转的思想

2、指Spring创建对象的过程中,将对象依赖属性通过配置进行注入

2、怎么用(两种方式)

1、set注入

2、构造注入

3、总结

1、IOC是一种控制反转的思想,而依赖注入是对IoC的一种具体的实现

2、Bean管理:Bean对象的创建,以及Bean对象中属性的赋值(或叫Bean对象之间关系的维护)

3、IoC容器在Spring的实现(接口)

1、Spring的IoC容器就是IoC思想的产品,IoC容器中管理的组件也叫bean,在创建bean之前,首先需要创建IoC容器,Spring提供了IoC容器的两种实现方式

1、BeanFactory

1、是IoC容器的基本实现,面向Spring本身,不提供给开发人员使用

2、最基本的容器

2、ApplicationContext

1、是BeanFactory的子接口,提供更多的特性

2、面向Spring的使用者

3、几乎所有场合都使用ApplicaationContext,而不是底层的BeanFactory

BeanFactory。

③ApplicationContext的主要实现类

类型名 简介
ClassPathXmlApplicationContext 通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象
FileSystemXmlApplicationContext 通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象
ConfigurableApplicationContext ApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、关闭和刷新上下文的能力。
WebApplicationContext 专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中。

image-20231225160958414

3、IOC、DI实现步骤

1、思路

image-20231225162907072

1、编写配置文件

配置元数据,既是编写交给SpringIoC容器管理组件的信息,配置方式有三种。

1、基于 XML 的配置元数据的基本结构:

<bean id="..." [1] class="..." [2]>  
    <!-- collaborators and configuration for this bean go here -->
</bean>
  <?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
    https://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="..." [1] class="..." [2]>  
    <!-- collaborators and configuration for this bean go here -->
  </bean>

  <bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
  </bean>
  <!-- more bean definitions go here -->
</beans>

2、\ 标签 == 组件信息声明

  • id 属性是标识单个 Bean 定义的字符串。

  • class 属性定义 Bean 的类型并使用完全限定的类名。

2、实例化IOC容器

1、提供给 ApplicationContext 构造函数的位置路径是资源字符串地址,允许容器从各种外部资源(如本地文件系统、Java CLASSPATH 等)加载配置元数据。

2、例子(伪代码)

//实例化ioc容器,读取外部配置文件,最终会在容器内进行ioc和di动作
ApplicationContext context = 
           new ClassPathXmlApplicationContext("services.xml", "daos.xml");

3、获取Bean(组件)

1、ApplicationContext 是一个高级工厂的接口,能够维护不同 bean 及其依赖项的注册表。通过使用方法 T getBean(String name, Class requiredType) ,您可以检索 bean 的实例。

2、例子(伪代码)

//创建ioc容器对象,指定配置文件,ioc也开始实例组件对象
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
//获取ioc容器的组件对象
PetStoreService service = context.getBean("petStore", PetStoreService.class);
//使用组件对象
List<String> userList = service.getUsernameList();

4、基于XML管理Bean

1、搭建子模块Spring6-ioc-xml1

1、搭建模块

1、搭建方式如:Spring-first

2、引入配置文件

1、引入Spring-first模块配置文件:beans.xml、log4j2.xml

3、添加依赖
<dependencies>
        <!--spring context依赖-->
        <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.2</version>
        </dependency>

        <!--junit5测试-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!--log4j2的依赖-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>2.19.0</version>
        </dependency>
    </dependencies>

3、实验一:获取bean

1、前提创建User类、还有TestUser类

2、User类

package com.atqt.spring6_first_ico_xml1;

public class User {
    private String name;
    private Integer age;

    public void run(){
        System.out.println("run..........");
    }
}

2、TestUser类

package com.atqt.spring6;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
//    创建Logger对象
    private Logger logger = LoggerFactory.getLogger(TestUser.class);

    @Test
    public void testUserObjeect(){
//        加载spring的配置文件,对象创建
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//        获取创建的对象
        User user = (User) context.getBean("user");
//        使用对象调用方法进行测试
        user.add();

//        手动写日志
        logger.info("#################执行调用成功");

    }

    @Test
    public void testUserObject1() throws Exception {
//        获取类的对象
        Class clazz = Class.forName("com.atqt.spring6.User");
//        调用方法创建对象
        User user = (User) clazz.getDeclaredConstructor().newInstance();
        System.out.println(user);
    }
}

3、bean.xml文件

<?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">
<!--    对象创建-->
    <bean id="user" class="com.atqt.spring6_first_ico_xml1.User"></bean>
</beans>
1、方式一:获取id
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//        根据id获取bean
        User user1 = (User) context.getBean("user");
        System.out.println("根据id获取bean"+user1);
2、方式二:根据类型获取
//        根据类型获取
        User user2 = (User) context.getBean("user");
        System.out.println("根据类型获取bean"+user2);
3、方式三:根据id和类型
//        根据id和类型获取bean
        User user3 = (User) context.getBean("user", User.class);
        System.out.println("根据id和类型获取bean"+user3);
4、注意

1、当根据类型获取bean时,要求IOC容器中指定类型的bean有且只有一个

2、如果bean配置了两个,而且根据类型获取bean的时候,就会报异常

3、异常原因是:只希望匹配1个单实例的bean对象,但是找到了2个

5、扩展

1、如果组件类实现了接口,根据接口类型可以获取bean吗

答案:可以,前提是bean唯一

2、如果一个接口有多个实现类,这些实现类都配置了bean,根据接口类型可以获取bean吗

答案:不可以,因为bean不唯一

6、结论

1、根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:『对象 instanceof 指定的类型』的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到。

2、java中,instanceof运算符用于判断前面的对象是否是后面的类,或其子类、实现类的实例。如果是返回true,否则返回false。也就是说:用instanceof关键字做判断时, instanceof

操作符的左右操作必须有继承或实现关系

3、实验二:IoC基于XML管理Bean依赖注入

1、创建一个类,给一个类中注入属性值

1、普通方法注入

1、就是创建一个类,定义两个私有属性

2、设置set方法,通过创建对象.set()进行值的赋予

3、也可以通过有参构造器,然后就可以在创建对象的时候,赋值

2、方法一:setter注入

1、先创建类,定义属性,设置get和set方法

package com.atqt.di;

public class Book {
    private String bname;
    private String author;

    public Book() {
    }
    public Book(String bname, String author) {
        this.bname = bname;
        this.author = author;
    }
    public String getBname() {
        return bname;
    }
    public void setBname(String bname) {
        this.bname = bname;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
//    原生写法
    public static void main(String[] args) {
        Book book = new Book();
        book.setBname("java");
        book.setBname("尚硅谷");
    }
//    构造器写法
    Book book1 = new Book("java1","尚硅谷111");
}

2、在Spring中进行配置

<?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">
    <!--        通过set方法注入-->
    <bean id="book" class="com.atqt.spring.iocxm.di.Book">
        <property name="bName" value="前端开发"></property>
        <property name="author" value="尚硅谷"></property>
    </bean>
</beans>

3、进行测试:编写测试类

package com.atqt.spring.iocxm.di;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBook {

    @Test
    public void testSetter(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-di.xml");
        Book book = context.getBean("book", Book.class);
        System.out.println(book);

    }
}

4、实验三:依赖注入—构造器注入

image-20231008201815879

1、传统方法注入

1、就是创建一个类的时候new xxx(参数1,参数2)

2、通过构造器

1、在Book类中添加有参构造器
//    有参构造器
    public Book(String bName, String author) {
        this.bName = bName;
        this.author = author;
        System.out.println("有参数执行了");
    }
2、配置bean
<!--    通过构造方法注入-->
    <bean id="bookCon" class="com.atqt.spring.iocxm.di.Book">
        <constructor-arg name="bName" value="java学习"></constructor-arg>
        <constructor-arg name="author" value="尚硅谷"></constructor-arg>

    </bean>
3、编写测试代码
    @Test
    public void testConst(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-di.xml");
        Book book = context.getBean("bookCon", Book.class);
        System.out.println(book);

    }

5、实验四:特殊值处理

1、字面量赋值

1、字面量赋值

2、就和普通赋值一样

<constructor-arg name="author" value="尚硅谷"></constructor-arg>
2、null值

1、就是如何表示null值

2、在配置中设置

    <!--        通过set方法注入-->
    <bean id="book" class="com.atqt.spring.iocxm.di.Book">
        <property name="others">
            <null></null>
        </property>
    </bean>
3、xml实体

1、就是在xml中的小括则号<不能随便写

2、使用xml实体代替

3、<:\<

4、>:\>

5、配置设置

    <!--        通过set方法注入-->
    <bean id="book" class="com.atqt.spring.iocxm.di.Book">
        <property name="others" value="<哈哈>"></property>
    </bean>
4、CDATA节

1、是xml中的特有的

2、可以包含xml中的特殊符号

3、配置设置

    <!--        通过set方法注入-->
    <bean id="book" class="com.atqt.spring.iocxm.di.Book">
        <property name="others">
            <value><![CDATA[a<bhhhhhh]]></value>
        </property>
    </bean>

6、实验五:为对象类型属性赋值

1、搭建前期环境

1、Emp类

package com.atqt.spring.iocxm.ditest;

public class Emp {

//    对象类型属性:员工属于某个部门
    private Dept dept;

    private String ename;
    private Integer age;
    public void work(){
        System.out.println(ename+"empWork......"+age);
        dept.info();
    }
    public Dept getDept() {
        return dept;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    public String getEname() {
        return ename;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

2、Dept类

package com.atqt.spring.iocxm.ditest;
//部门
public class Dept {
    private String dName;

    public void info(){
        System.out.println("部门输出.........."+dName);
    }

    public String getdName() {
        return dName;
    }

    public void setdName(String dName) {
        this.dName = dName;
    }
}
2、方法一:外部bean引入

1、先用配置文件创建一个bean-ditest.xml 文件

2、创建两个类用bean标签创建

3、然后在一个新的bean中引入创建好的id=dept的bean标签,然后再根据id注入属性值(就相当于引入外部的bean)

4、个人理解:就相当于使用两个配置对象变量,然后使用ref标签调用类,从而达到外部引入的效果

4、格式

<bean id="xxxx" value="xxxx">
<bean id="yyyy" value="xxxx">
<.... ref="所需要引入的外部类">
其他该赋值赋值,该给定义属性就定义属性

5、代码实现

        <!--
        1、创建dep和emp类的对象
        2、在emp的bean中,使用property引入dept的bean
        -->
        <bean id="dept" class="com.atqt.spring.iocxm.ditest.Dept">
                <property name="dName" value="安保部"></property>
        </bean>
        <bean id="emp" class="com.atqt.spring.iocxm.ditest.Emp">
<!--                最普通的属性注入-->
                <property name="ename" value="lucy"></property>
                <property name="age" value="50"></property>
<!--                注入对象类型的属性-->
            <property name="dept" ref="dept"></property>

        </bean>
3、方法二:内部类引用

1、就是先用配置文件创建一个bean,bean中创建一个类对象A

2、在类对象A中的创建一个property标签

3、在这个property标签中创建一个bean标签,bean中创建一个对象B

4、这个就是内部类的引用

5、例子

<bean id="emp2" class="com.atqt.spring.iocxm.ditest.Emp">
        <property name="ename" value="玛卡巴卡"></property>
        <property name="age" value="55"></property>
<!--        内部bean方式注入-->
        <property name="dept">
            <bean id="dept2" class="com.atqt.spring.iocxm.ditest.Dept">
                <property name="dName" value="牛马部"></property>
            </bean>
        </property>
    </bean>
4、方法三:级联属性赋值

1、就是创建两个bean,用bean创建两个对象

2、在对象A中的property中引入对象B,然后通过对象B.xxx属性来操作

3、代码实现

<!--    第三种方式 级联赋值-->
    <bean id="dept3" class="com.atqt.spring.iocxm.ditest.Dept">
        <property name="dName" value="哈哈哈哈"></property>
    </bean>

    <bean id="emp3" class="com.atqt.spring.iocxm.ditest.Emp">
        <property name="ename" value="神仙"></property>
        <property name="age" value="30"></property>
        <property name="dept" ref="dept3"></property>
        <property name="dept.dName" value="哈哈哈哈2"></property>
    </bean>

7、实验六:为数组类型属性赋值

1、环境

1、环境和实验五一样

2、需要在Emp类中添加一个数组类型变量loves

2、方法

1、格式

<!--        注入数组类型-->
        <property name="loves">
            <array>
                <value>数组属性值</value>
                <value>数组属性值</value>
                <value>数组属性值</value>
            </array>
        </property>
3、实现

1、bean配置文件实现

<!--    注入数组类型属性-->
    <bean id="dept" class="com.atqt.spring.iocxm.ditest.Dept">
        <property name="dName" value="技术部"></property>
    </bean>

    <bean id="emp" class="com.atqt.spring.iocxm.ditest.Emp">
<!--        注入普通的属性值-->
        <property name="ename" value="lucy"></property>
        <property name="age" value="20"></property>
<!--        对象类型的属性-->
        <property name="dept" ref="dept"></property>
<!--        注入数组类型-->
        <property name="loves">
            <array>
                <value>抽烟</value>
                <value>唱歌</value>
                <value>跳舞</value>
            </array>
        </property>
    </bean>

8、实验七:为集合list类型属性赋值

1、环境

1、和实验六一样

2、需要多在Dept中添加一个list集合对象

private List<Emp> empList;
相应的get和set方法

3、在Dept类中info方法遍历一下集合,主要是方便实现

2、代码实现
<!--    创建集合类型传入emp对象-->
    <bean id="emp1" class="com.atqt.spring.iocxm.ditest.Emp">
        <property name="ename" value="lucky1"></property>
        <property name="age" value="20"></property>
    </bean>
    <bean id="emp2" class="com.atqt.spring.iocxm.ditest.Emp">
        <property name="ename" value="lucky2"></property>
        <property name="age" value="22"></property>
    </bean>

    <bean id="dept" class="com.atqt.spring.iocxm.ditest.Dept">
        <property name="dName" value="技术部"></property>
        <property name="empList">
            <list>
                <ref bean="emp1"></ref>
                <ref bean="emp2"></ref>
            </list>
        </property>
    </bean>

9、实验八:为Map类型数据赋值

1、环境

1、Student.java

package com.atqt.spring.iocxm.dimap;

import java.util.Map;

public class Student {
    private String sId;
    private String sName;

    private Map<String ,Teacher> teacherMap ;

    public Map<String, Teacher> getTeacherMap() {
        return teacherMap;
    }

    public void setTeacherMap(Map<String, Teacher> teacherMap) {
        this.teacherMap = teacherMap;
    }

    public void run(){
        System.out.println("学生编号"+sId+"学生的姓名"+sName);
        System.out.println(teacherMap);
    }

    public String getsId() {
        return sId;
    }

    public void setsId(String sId) {
        this.sId = sId;
    }

    public String getsName() {
        return sName;
    }

    public void setsName(String sName) {
        this.sName = sName;
    }

}

2、Teacher.java

package com.atqt.spring.iocxm.dimap;

public class Teacher {
    private String tId;
    private String tName;

    public String gettId() {
        return tId;
    }

    public void settId(String tId) {
        this.tId = tId;
    }

    public String gettName() {
        return tName;
    }

    public void settName(String tName) {
        this.tName = tName;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "tId='" + tId + '\'' +
                ", tName='" + tName + '\'' +
                '}';
    }
}
2、格式
<bean id="student" class="com.atqt.spring.iocxm.dimap.Student">
            <property name="sId" value="100"></property>
            <property name="sName" value="王五老师"></property>

<!--            在学生bean中注入map集合类型属性-->
            <property name="teacherMap">
                <map>
                    <entry>
                        <key>
                        <!--key:的值-->
                            <value>101</value>
                        </key>
                        <!--           value:注入的对象-->
                        <ref bean="teacher1"></ref>
                    </entry>
                </map>
            </property>
        </bean>
3、配置文件

1、bean-dimap.xml

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
        <bean id="teacher1" class="com.atqt.spring.iocxm.dimap.Teacher">
            <property name="tId" value="001"></property>
            <property name="tName" value="张三老师"></property>
        </bean>

        <bean id="teacher2" class="com.atqt.spring.iocxm.dimap.Teacher">
            <property name="tId" value="002"></property>
            <property name="tName" value="张三老师"></property>
        </bean>

        <bean id="teacher3" class="com.atqt.spring.iocxm.dimap.Teacher">
            <property name="tId" value="003"></property>
            <property name="tName" value="李四老师"></property>
        </bean>

        <bean id="student" class="com.atqt.spring.iocxm.dimap.Student">
            <property name="sId" value="100"></property>
            <property name="sName" value="王五老师"></property>

<!--            在学生bean中注入map集合类型属性-->
            <property name="teacherMap">
                <map>
                    <entry>
                        <key>
                            <value>101</value>
                        </key>
                        <ref bean="teacher1"></ref>
                    </entry>
                    <entry>
                        <key>
                            <value>102</value>
                        </key>
                        <ref bean="teacher2"></ref>
                    </entry>
                    <entry>
                        <key>
                            <value>103</value>
                        </key>
                        <ref bean="teacher3"></ref>
                    </entry>

                </map>
            </property>
        </bean>

</beans>

2、测试代码

1、Test.java

package com.atqt.spring.iocxm.dimap;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-dimap.xml");
        Student student = (Student) context.getBean("student");
        student.run();
    }
}

10、实验九:为引用集合类型在bean

1、环境

1、新加一个Lesson.java

package com.atqt.spring.iocxm.dimap;

public class Lesson {
    private String lessonName;

    public String getLessonName() {
        return lessonName;
    }

    public void setLessonName(String lessonName) {
        this.lessonName = lessonName;
    }

    @Override
    public String toString() {
        return "Lesson{" +
                "lessonName='" + lessonName + '\'' +
                '}';
    }
}

2、在Student.java中添加一个List

private List<Lesson> lessonList;
2、配置文件

1、bean-diref.xml

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="teacher10" class="com.atqt.spring.iocxm.dimap.Teacher">
        <property name="tId" value="001"></property>
        <property name="tName" value="张三老师"></property>
    </bean>

    <bean id="teacher11" class="com.atqt.spring.iocxm.dimap.Teacher">
        <property name="tId" value="002"></property>
        <property name="tName" value="李四"></property>
    </bean>

    <bean id="student" class="com.atqt.spring.iocxm.dimap.Student">
        <property name="sId" value="张三"></property>
        <property name="sName" value="李四"></property>
<!--   注入list、map类型属性 -->
        <property name="lessonList" ref="lessonList"></property>
        <property name="teacherMap" ref="teacherMap"></property>
    </bean>
<!--    写这个变量的时候,需要注意xmlns的规范-->

    <util:list id="lessonList">
        <ref bean="lesson1"></ref>
        <ref bean="lesson2"></ref>
        <ref bean="lesson3"></ref>
    </util:list>

    <util:map id="teacherMap">
        <entry>
            <key>
                <value>10000</value>
            </key>
            <ref bean="teacher10"></ref>
        </entry>
        <entry>
            <key>
                <value>10001</value>
            </key>
            <ref bean="teacher11"></ref>
        </entry>
    </util:map>

    <bean id="lesson1" class="com.atqt.spring.iocxm.dimap.Lesson">
        <property name="lessonName" value="java开发"></property>
    </bean>

    <bean id="lesson2" class="com.atqt.spring.iocxm.dimap.Lesson">
        <property name="lessonName" value="python开发"></property>
    </bean>

    <bean id="lesson3" class="com.atqt.spring.iocxm.dimap.Lesson">
        <property name="lessonName" value="测试测试"></property>
    </bean>
</beans>
3、注意

1、这个util:map util:list 都是需要导入,命名空间

2、不然会出现报错问题

11、p命名空间

1、环境

1、和以上一样

2、注意:需要导入对应的命名空间格式

xmlns:p="http://www.springframework.org/schema/p"
2、配置文件
    <bean id="studentp" class="com.atqt.spring.iocxm.dimap.Student"
    p:sId="100" p:teacherMap-ref="teacherMap"  >

    </bean>

12、实验十:引入外部属性文件(以jdbc配置数据库为例)

image-20231011173637600

1、作用

1、使用场景:jdbc的连接,需要引入外部的.properties文件

2、创建配置文件,引入context命名空间

3、引入属性文件,使用表达式完成注入

4、如果有内容需要修改,就不用修改上线所需的内容,

2、加入配置文件的依赖

1、pom.xml

 <!-- MySQL驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>

<!-- 数据源 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.15</version>
</dependency>
3、创建外部文件

1、jdbc.properties

jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver
4、引入属性文件

1、引入context名称空间

13、实验十一:bean的作用域

1、概念

1、配置bean标签的scope属性来制定bean的作用域范围

取值 含义 创建对象的时机
singleton(默认) 在IOC容器中,这个bean的对象始终为单实例 IOC容器初始化时
prototype 这个bean在IOC容器中有多个实例 获取bean时

2、如果是在WebApplicationContext环境下还会有另外几个作用域(但不常用):

取值 含义
request 在一个请求范围内有效
session 在一个会话范围内有效
2、演示例子

1、创建以类User

package com.atqt.spring.iocxm.score;

public class User {

}

2、创建配置文件bean-scope.xml

<?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">
        <!--    多实例的例子-->
        <bean id="user" class="com.atqt.spring.iocxm.score.User" scope="prototype"></bean>
</beans>

3、进行测试类的创建和运行

package com.atqt.spring.iocxm.score;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestU {
    @Test
    public void demo1(){
//        多实例测试
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-scope.xml");
//        如果是scope="prototype",那就是多实例,singleton(默认)就是单实例
        User user1 = context.getBean(User.class);
        User user2 = context.getBean(User.class);
//        创建了2个对象呢
        System.out.println(user1==user2);
    }
}

14、实验十二:bean生命周期

1、具体的生命周期过程

1、bean对象的创建(调用无参构造器)

2、给bean对象设置属性(属性注入)

3、bean的后置处理器(初始化之前0

4、bean对象的初始化

5、bean后置处理器(初始化之后)

6、bean对象创建完成了,能够使用

7、bean对象销毁(配置指定的销毁方法)

8、IOC容器关闭了

2、补充标签

1、init-method:初始化标签

2、destroy-method:结束标签

#使用结束方法就需要创建实例化对象的类ClassPathXmlApplicationContext
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-life.xml");
context.close();
3、后置处理器

1、创建一个类,类继承BeanPostProcessor

2、重写接口中的两个方法

3、后置处理器,初始化之前的方法

default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return xxxxx;
    }

5、注意:bean创建接口的后置处理器,是针对IOC容器中的所有bean都会执行

6、后置处理器,初始化之后的方法

@Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return xxxx;
    }

7、配置设置文件

#就是和为对象类型属性赋值的操作一样

15、实验十三:FactoryBean

1、简介

1、是spring提供的一种整合的第三方框架的常用机制

2、获取bean的时候得到的不是class属性中配置的这个类的对象,而是getObject()方法的返回值

3、可以把繁杂的细节机制屏蔽起来

4、将来我们整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqSessionFactory对象

2、例子

1、编写MyFactoryBean.java

package com.atqt.spring.iocxm.factorybean;

import com.atqt.spring.iocxm.score.User;
import org.springframework.beans.factory.FactoryBean;

public class MyFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new User();
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }
}

2、User.java

随便定义一些方法

3、配置文件设置

<?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">
    <bean id="user" class="com.atqt.spring.iocxm.factorybean.MyFactoryBean"></bean>
</beans>

16、实验十四:基于xml自动装配

1、理解

1、自动装配:根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类,类型或接口类型属性赋值

image-20231011234555917

2、配置的两个概念

1、自动装配方式:byType

①根据类型匹配IOC容器中的某个兼容类型的bean,为属性自动赋值

②若在IOC中,没有任何一个兼容类型的bean能够为属性值赋值,则该属性不装配,因为默认值为null

③若IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException

2、自定装配方式:byName

①将自动装配的属性的属性名,作为bean的id在IONC容器中匹配相对应的bean进行赋值

3、例子

1、创建UserController.java

package com.atqt.spring.iocxm.auto.controller;

import com.atqt.spring.iocxm.auto.service.UserService;
import com.atqt.spring.iocxm.auto.service.UserServiceImpl;

public class UserController {
    private UserService userService;
    public void addUser(){
        System.out.println("controller方法执行了");
        UserService userService = new UserServiceImpl();
        userService.addUserService();
    }

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

}

2、创建UserDao.java

package com.atqt.spring.iocxm.auto.dao;

public interface UserDao {
    public void addUserDao();
}

3、创建UserDaoImpl.java

package com.atqt.spring.iocxm.auto.dao;

public class UserDaoImpl implements UserDao{

    @Override
    public void addUserDao() {
        System.out.println("UserDao方法执行了");
    }
}

4、创建UserService.java

package com.atqt.spring.iocxm.auto.service;

public interface UserService {
    public void addUserService();
}

5、创建UserServiceImpl.java

package com.atqt.spring.iocxm.auto.service;

import com.atqt.spring.iocxm.auto.dao.UserDao;
import com.atqt.spring.iocxm.auto.dao.UserDaoImpl;

public class UserServiceImpl implements UserService {
    private UserDao userDao;
    @Override
    public void addUserService() {
        System.out.println("userServiceImpl方法执行了");
        UserDao userDao = new UserDaoImpl();
        userDao.addUserDao();
    }

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

6、配置文件bean-auto.xml

<?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">
    <!--    <bean id="userController" class="com.atqt.spring.iocxm.auto.controller.UserController"-->
    <!--          autowire="byType">-->
    <!--<!–根据类型自动装配–>-->
    <!--    </bean>-->
    <!--    <bean id="userService" class="com.atqt.spring.iocxm.auto.service.UserServiceImpl"-->
    <!--          autowire="byType" >-->

    <!--    </bean>-->
    <!--    <bean id="UserDao" class="com.atqt.spring.iocxm.auto.dao.UserDaoImpl">-->

    <!--    </bean>-->

    <!--根据名称自动装配-->
    <bean id="userController" class="com.atqt.spring.iocxm.auto.controller.UserController"
          autowire="byName">
    </bean>
    <bean id="userService" class="com.atqt.spring.iocxm.auto.service.UserServiceImpl"
          autowire="byName">

    </bean>
    <bean id="UserDao" class="com.atqt.spring.iocxm.auto.dao.UserDaoImpl">

    </bean>

</beans>

7、进行测试TestUser.java

package com.atqt.spring.iocxm.auto.service;

import com.atqt.spring.iocxm.auto.controller.UserController;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    @Test
    public void demo01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-auto.xml");
        UserController userController = (UserController) context.getBean("userController");
        userController.addUser();
    }
}

5、基于注解管理Bean

1、概念

1、java5开始增加注解的支持,是代码的特殊标记,可以在编译、类加载和运行时被读取,执行响应的处理。

2、开发人员可以通过注解在不改变原有代码和逻辑的情况下,在源代码中嵌入开发资源

3、spring2.5开始支持注解

4、我们可以使用注解实现自动装配,简化Spring和xml的配置

2、spring自动装配注解的实现步骤

1、引入依赖

2、开启组件扫描

3、使用注解定义bean

4、依赖注入

3、创建测试模块

1、创建一个模块,然后把相应的包导入

2、把log4j2.xml设置好

4、开启扫描组件

1、spring默认是不使用注解装配bean的

2、所以我们需要在spring的xml中进行配置

3、然后通过context:component-scan元素,开启Spring Beans的自动扫描功能

4、开启后就会自动的扫描指定的包,以及包下的所有类

5、如果有使用@component注解,就会将该类装到注解里面,就相当于是IOC中的把普通pojo实例化到spring容器中,相当于配置文件中的\

6、扫描组件配置

<?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-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
        <!--开启组件扫描功能-->

</beans>
1、情况一:最基本的扫描方式
        <!--开启组件扫描功能-->
        <context:component-scan base-package="com.atqt"></context:component-scan>
2、情况二:指定要排除的组件(基本了解)
                <!-- context:exclude-filter标签:指定排除规则 -->
                <!--
                     type:设置排除或包含的依据
                    type="annotation",根据注解排除,expression中设置要排除的注解的全类名
                    type="assignable",根据类型排除,expression中设置要排除的类型的全类名
                -->
                <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
                <!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
        </context:component-scan>
3、情况三:仅扫描指定组件
<context:component-scan base-package="com.atguigu" use-default-filters="false">
    <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <!-- 此时必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类 -->
    <!-- 
         type:设置排除或包含的依据
        type="annotation",根据注解排除,expression中设置要排除的注解的全类名
        type="assignable",根据类型排除,expression中设置要排除的类型的全类名
    -->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <!--<context:include-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>

5、使用注解定义Bean

1、内容

1、spring提供了以下多个注解,这些注解可以直接标注在java类上,将他们定义成Spring Bean

2、内容

注解 说明
@Component 该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。
@Repository 该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller 该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
2、基本使用例子

1、创建一个User.java

package com.atqt.spring6.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component(value = "user") //== <bean id="user" class="xxx"
public class User {
}

2、bean.xml

<?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-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
        <!--开启组件扫描功能-->
        <context:component-scan base-package="com.atqt.spring6">
                <!-- context:exclude-filter标签:指定排除规则 -->
                <!--
                     type:设置排除或包含的依据
                    type="annotation",根据注解排除,expression中设置要排除的注解的全类名
                    type="assignable",根据类型排除,expression中设置要排除的类型的全类名
                -->
                <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
                <!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
        </context:component-scan>

<!--        排除指定的扫描组件-->

</beans>

6、实验一:@Autowired注入

1、内容

1、单独使用@Autowired注入,根据默认类型匹配【默认是byType】

2、源码

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//使用的地方
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    //要求这个值必须存在
    boolean required() default true;
}

3、可以在注入的地方一

构造方法上
方法上
形参上
属性上
注解上

4、可以注解的地方二

①该注解有一个required属性,默认值是true,表示在注入的时候要求被注入的Bean必须是存在的

②如果不存在则报错。如果required属性设置为false,表示注入的Bean存在或者不存在都没关系

③存在的话就注入,不存在也不报错

2、场景一:属性注入

1、对模块的xml文件进行配置扫描

2、创建UserDao.java

package com.atqt.spring6.bean.autowired.dao;

public interface UserDao {
    public void add();
}

3、创建UserDaoImpl.java

package com.atqt.spring6.bean.autowired.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao{

    @Override
    public void add() {
        System.out.println("UserDaoImpl执行了....");
    }
}

4、UserService.java

package com.atqt.spring6.bean.autowired.service;

public interface UserService {
    public void add();
}

5、UserServiceImpl.java

package com.atqt.spring6.bean.autowired.service;

import com.atqt.spring6.bean.autowired.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{
//    注入dao
//    第一种方式 属性注入
    @Autowired
    private UserDao userDao;

    @Override
    public void add() {
        System.out.println("UserServiceImpl执行了。。。。");
        userDao.add();
    }
}

6、UserController.java

package com.atqt.spring6.bean.autowired.controller;

import com.atqt.spring6.bean.autowired.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
//    注入Service
    //方式一:第一种注入属性注入
    @Autowired//根据类型找到对应的对象
    private UserService userService;

    public void add(){
        System.out.println("UserController执行了。。。。");
        userService.add();
    }

}

7、测试使用注解TestUser.java

package com.atqt.spring6.bean;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        User user = (User) context.getBean(User.class);
        System.out.println(user);
    }
}
3、场景二:set方法注入

1、基本内容和场景一类似

2、UserDao.java一样

3、UserDaoImpl一样

4、UserService.java一样

5、UserServiceImpl.java

//    第二种方式
    private UserDao userDao;

    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

6、UserController.java

package com.atqt.spring6.bean.autowired.controller;

import com.atqt.spring6.bean.autowired.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
//    注入Service
//    //方式一:第一种注入属性注入
//    @Autowired//根据类型找到对应的对象
//private UserService userService;
//    方式二:set注入

    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void add(){
        System.out.println("UserController执行了。。。。");
        userService.add();
    }

}

7、测试使用注解TestUser.java

package com.atqt.spring6.bean;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        User user = (User) context.getBean(User.class);
        System.out.println(user);
    }
}
4、场景三:构造方法注入

1、

1、基本内容和场景一类似

2、UserDao.java一样

3、UserDaoImpl一样

4、UserService.java一样

5、UserServiceImpl.java

package com.atqt.spring6.bean.autowired.service;

import com.atqt.spring6.bean.autowired.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{
//    注入dao
//    第一种方式 属性注入
//    @Autowired
//    private UserDao userDao;
//
//    @Override

//    第二种方式
//    private UserDao userDao;
//
//    @Autowired
//    public void setUserDao(UserDao userDao) {
//        this.userDao = userDao;
//    }

//    第三种方法
    private UserDao userDao;
    @Autowired

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    public void add() {
        System.out.println("UserServiceImpl执行了。。。。");
        userDao.add();
    }
}

6、UserController.java

package com.atqt.spring6.bean.autowired.controller;

import com.atqt.spring6.bean.autowired.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
//    注入Service
//    //方式一:第一种注入属性注入
//    @Autowired//根据类型找到对应的对象
//private UserService userService;
//    方式二:set注入

//    private UserService userService;
//    @Autowired
//    public void setUserService(UserService userService) {
//        this.userService = userService;
//    }

//    第三种方法:构造器注入
    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    public void add(){
        System.out.println("UserController执行了。。。。");
        userService.add();
    }

}

7、测试使用注解TestUser.java

package com.atqt.spring6.bean.autowired;

import com.atqt.spring6.bean.autowired.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        UserController  userController =  context.getBean(UserController.class);
        userController.add();

    }

}
5、场景四:构造方法注入

1、基本内容和场景一类似

2、UserDao.java一样

3、UserDaoImpl一样

4、UserService.java一样

5、UserServiceImpl.java

package com.atqt.spring6.bean.autowired.service;

import com.atqt.spring6.bean.autowired.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{
//    注入dao
//    第一种方式 属性注入
//    @Autowired
//    private UserDao userDao;
//
//    @Override

//    第二种方式
//    private UserDao userDao;
//
//    @Autowired
//    public void setUserDao(UserDao userDao) {
//        this.userDao = userDao;
//    }

////    第三种方法
//    private UserDao userDao;
//    @Autowired
//
//    public UserServiceImpl(UserDao userDao) {
//        this.userDao = userDao;
//    }

//    第四种方式:形参注入
    private UserDao userDao;

    public UserServiceImpl(@Autowired UserDao userDao) {
        this.userDao = userDao;
    }

    public void add() {
        System.out.println("UserServiceImpl执行了。。。。");
        userDao.add();
    }
}

6、UserController.java

package com.atqt.spring6.bean.autowired.controller;

import com.atqt.spring6.bean.autowired.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {
//    注入Service
//    //方式一:第一种注入属性注入
//    @Autowired//根据类型找到对应的对象
//private UserService userService;
//    方式二:set注入

//    private UserService userService;
//    @Autowired
//    public void setUserService(UserService userService) {
//        this.userService = userService;
//    }

////    第三种方法:构造器注入
//    private UserService userService;
//
//    @Autowired
//    public UserController(UserService userService) {
//        this.userService = userService;
//    }

//    第四种方式:形参注入
    private UserService userService;

    public UserController(@Autowired UserService userService) {
        this.userService = userService;
    }

    public void add(){
        System.out.println("UserController执行了。。。。");
        userService.add();
    }

}

7、测试使用注解TestUser.java

package com.atqt.spring6.bean.autowired;

import com.atqt.spring6.bean.autowired.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        UserController  userController =  context.getBean(UserController.class);
        userController.add();

    }

}
6、场景五:只有一个有参构造函数,可以不注释!

1、注意:有且只有一个有参构造函数,才可以不注释

7、场景六:@Autowired和@Qualifier注解联合

1、UserDao一样UserService一样

2、添加一个UserRedisDaoImpl.java

package com.atqt.spring6.bean.autowired.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserRedisDaoImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("UserRedisDaoImpl运行了....");
    }
}

3、修改UserServiceImpl.java

package com.atqt.spring6.bean.autowired.service;

import com.atqt.spring6.bean.autowired.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{

//    第五种方法:根据两个注解进行注入
    @Autowired
    @Qualifier(value = "userRedisDaoImpl")
    private UserDao userDao;

    public void add() {
        System.out.println("UserServiceImpl执行了。。。。");
        userDao.add();
    }
}

4、注意要写注解

7、实验二:@Resource注入

1、@Resource和 @Autowired比较

1、@Resource注解可以完成属性注入

2、@Resource注解是JDK扩展包中的,是jdk的一部分,是标准注解,更有通用性

3、Autowired注解是Spring的

4、@Resource默认是根据名称装配byName,未指定name时,使用属性名称作为name

5、如果找不到name,就会自动启动通过类型byType装配。

6、@Autowired注解默认是根据类型装配,如果想根据名称装配,需要配合@Qualifier注解一起用

7、@Resource注解用在属性上、setter方法上

8、@Autowired注解,用在属性上、setter方法上、构造方法上、构造方法参数上

9、@Resource注解属于jdk扩展包,所以不做jdk当中,需要引入额外的包【jdk8不要,jdk高于11或者低于jdk8需要引入】

10、依赖

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>
2、场景一:根据name注入

1、UserDaoImp.java

package com.atqt.spring6.bean.resource.dao;

import org.springframework.stereotype.Repository;

@Repository("myUserDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void add() {
        System.out.println("UserDaoImpl执行了....");
    }
}

2、UserRedisDaoImpl.java

package com.atqt.spring6.bean.resource.dao;

import org.springframework.stereotype.Repository;

@Repository("myUserRedisDao")
public class UserRedisDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("UserRedisDaoImpl运行了....");
    }
}

3、UserServiceImpl.java

package com.atqt.spring6.bean.resource.service;

import com.atqt.spring6.bean.resource.dao.UserDao;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Service(value = "myUserService")
public class UserServiceImpl implements UserService {

    @Resource(name = "myUserDao")
    private UserDao myUserDao;

    public void add() {
        System.out.println("UserServiceImpl执行了。。。。");
        myUserDao.add();
    }
}

4、TestUser.java

package com.atqt.spring6.bean.resource;

import com.atqt.spring6.bean.resource.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUser {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        UserController userController =  context.getBean(UserController.class);
        userController.add();
    }
}
3、测试异常

1、根据异常信息得知:显然当通过name找不到的时候,自然会启动byType进行注入,以上的错误是因为UserDao接口下有两个实现类导致的。所以根据类型注入就会报错。

2、@Resource的set注入可以自行测试

4、总结

1、@Resource注解:默认byName注入,没有指定name时把属性名当做name,根据name找不到时,才会byType注入。byType注入时,某种类型的Bean只能有一个

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇