Spring笔记

269 阅读13分钟

1.学习目标

  1. 能够说出 Spring 的体系结构
  2. 能够编写 IOC 入门案例
  3. 能够编写 DI 入门案例
  4. 能够配置 setter 方式注入属性值
  5. 能够配置构造方式注入属性值
  6. 能够理解什么是自动装配

2.Spring介绍

2.1 学习内容

  • 初识 Spring
  • Spring 系统架构
  • 核心概念

2.2 为什么要学Spring

image-20231026102510110.png

2.3 初识Spring

image-20231026102910978.png

2.4 Spring发展史

image-20231026103125064.png

2.5 Spring Framework系统架构

image-20231026103427239.png

2.6 Spring Framework学习线路

image-20231026104109336.png

3.Spring核心概念

3.1 学习内容

  • IoC 入门案例
  • DI 入门案例

3.2 业务层和数据层耦合问题

1、图解

image-20231026105059988.png

2、问题

  • 如果业务层中的数据对象需要变更,则需要手动修改业务层的代码,耦合度过高

3、代码书写现状

  • 耦合度偏高

4、解决方案

  • 使用对象时,在程序中不要主动使用 new 产生对象,转换为由外部提供对象

3.3 IoC

  • IoC(Inversion of Control):控制反转
  • 对象的创建控制权由程序转移到 外部,这种思想称为控制反转
  • 即使用对象时,由主动 new 产生对象转换为 由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转
  • Spring 技术对 IoC 思想进行了实现:
    • Spring 提供了一个容器,称为 IoC 容器,用来充当 IoC 思想中的“外部”
    • IoC 容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在 IoC 容器中统称为 Bean

3.4 DI

  • DI(Dependency Injection):依赖注入
  • 在容器中建立 beanbean 之间的依赖关系的整个过程,称为依赖注入

image-20231026105954212.png

3.5 小结

  • Spring 目标:充分解耦

    • 使用 IoC 容器管理 bean(IoC)
    • IoC 容器内将有依赖关系的 bean 进行关系绑定(DI
  • Spring 最终效果:

    • 使用对象时不仅可以直接从 IoC 容器中获取
    • 获取到的 bean 已经绑定了所有的依赖关系
  • IoC/DI 思想:

    • IOC:对象创建控制权由程序转移到外部的过程
    • DIIoC 容器内将有依赖关系的 bean 进行关系绑定(属性赋值)
  • IoC 容器:

    • spring 提供了一个容器,称为 IoC 容器,用来充当 IoC 思想中的“外部”
  • Bean 概念:

    • IoC 容器创建或被管理的对象在 IoC 容器中统称为 Bean

4.IoC入门案例

4.1 目标

  • 创建 BookDaoImpl 对象,将 BookDaoImpl 对象放入 springIOC 容器

4.2 思路

  • 【第一步】:导入 Spring 坐标

image-20231026112404366.png

  • 【第二步】:定义 Spring 管理的类(接口)

image-20231026112518935.png

  • 【第三步】:创建 Spring 配置文件,配置对应类作为 Spring 管理的 bean

image-20231026112654389.png

  • 【第四步】:调用 IOC 容器中对象

image-20231026115431650.png

4.3 示例

1、第一步:创建项目

  • 创建 Maven 项目

image-20231026113358075.png

  • 输入项目名称 01_spring_ioc_di

image-20231026113503151.png

2、第二步:添加依赖

  • 修改 pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>01_spring_ioc_di</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- 1、spring核心依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <!-- 2、测试依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3、第三步:数据层

  • 定义 dao 层接口:
package com.itheima.dao;

public interface BookDao {
    void save();
}
  • 定义 dao 层实现类:
package com.itheima.dao.impl;

import com.itheima.dao.BookDao;

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save");
    }
}

4、第四步:业务层

  • 定义 service 层接口:
package com.itheima.service;

public interface BookService {
    void save();
}
  • 定义 service 层实现类:
package com.itheima.service.impl;

import com.itheima.dao.BookDao;
import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;

public class BookServiceImpl implements BookService {

    private BookDao bookDao = new BookDaoImpl();

    public void save() {
        System.out.println("bookService 保存数据");
        bookDao.save();
    }
}

5、第五步:定义配置

  • 新建 application.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">

    <!--
         1、目标:创建BookDaoImpl对象,将BookDaoImpl对象放入spring的IOC容器
         2、实现:BookDao bookDao = new BookDaoImpl();
         3、步骤:使用IOC容器创建BookDaoImpl对象
            <bean id="" class="">:使用IOC容器创建对象
            id:设置对象别名,这个id值必须唯一,便于以后从IOC容器中获取这个对象
            class:设置对那个类全名生成对象
    -->

    <!--
        4、bean标签: 使用IoC容器创建对象
            class: 要创建对象的类名
            id: 唯一标识, 理解为对象的名字
            name: bean的别名
            scope: bean的作用范围, 默认是singleton单例, prototype多例,每次获取都是新的对象
            init-method: 对象初始化方法
            destroy-method: 对象销毁的方法, 如果是多例,不会执行销毁方法
    -->

    <!-- 5、相当于 bookDao = new BookDaoImpl() -->
    <bean class="com.itheima.dao.impl.BookDaoImpl" id="bookDao"></bean>

</beans>

6、第六步:测试

package com.itheima.test;

import com.itheima.dao.BookDao;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BookTest {
    @Test
    public void testGetBean() {
        // 1. 让Spring去解析application.xml,使用IoC容器创建Bean
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

        // 2. 从IoC容器中获取Bean
        BookDao bookDao = (BookDao) context.getBean("bookDao");
        System.out.println("bookDao = " + bookDao);

        // 3. 调用对象的方法
        bookDao.save();

        // 4.关闭IoC容器
        context.close();
    }
}
  • ==效果==:

image-20231026121023748.png

4.4 idea中创建spring配置文件

  • 右键 resources 目录,然后依次选择以下内容

image-20231026114652109.png

4.5 bean标签

  • 作用:使用 IoC 容器创建对象
  • class 属性:要创建对象的类名
  • id 属性:唯一标识, 理解为对象的名字

5.DI入门案例

5.1 问题

  • 如何将 IOC 容器中 BookDao 对象注入(DI)到 BookServiceImpl?

5.2 思路

  • 【第一步】:删除使用 new 的形式创建对象的代码

image-20231026142141438.png

  • 【第二步】:提供依赖对象对应的 setter 方法

image-20231026142247451.png

  • 【第三步】:配置 servicedao 之间的关系

image-20231026142442776.png

5.3 示例

1、第一步:创建项目

  • 新建 02_spring_di 项目

image-20231026145712193.png

2、第二步:添加依赖

  • 修改 pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>02_spring_di</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>
        <!-- 1、spring核心依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <!-- 2、测试依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3、第三步:数据层

  • 定义 dao 层接口:
package com.itheima.dao;

public interface BookDao {
    void save();
}
  • 定义 dao 层实现类:
package com.itheima.dao.impl;

import com.itheima.dao.BookDao;

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save");
    }
}

4、第四步:业务层

  • 定义 service 层接口:
package com.itheima.service;

public interface BookService {
    void save();
}
  • 定义 service 层实现类:
package com.itheima.service.impl;

import com.itheima.dao.BookDao;
//import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;

public class BookServiceImpl implements BookService {
    // 1、第一步:删除以下代码,定义私有属性不初始化
    // private BookDao bookDao = new BookDaoImpl();
    private BookDao bookDao;

    // 2、第二步:提供set方法
    // alt+insert
    public void setBookDao(BookDao bookDao) {
        System.out.println("BookServiceImpl 使用setBookDao给成员变量赋值");
        this.bookDao = bookDao;
    }

    public void save() {
        System.out.println("bookService 保存数据");
        bookDao.save();
    }
}

5、第五步:定义配置

  • 新建 application.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">


    <!--
        1、目标:创建BookService对象  并将BookDaoImpl对象依赖注入(DI)到属性中
        2、步骤1:创建BookServiceImpl对象,将BookServiceImpl对象放入spring的IOC容器
        3、步骤2:调用方法 public void setBookDao(BookDao bookDao) 将id="bookDao"对象传入
            <property> 调用set封装方法
            name="bookDao" 调用setBookDao方法
            ref="bookDao" 获取IOC容器中 id="bookDao" 对象
    -->


    <!-- 相当于 bookDao = new BookDaoImpl() -->
    <bean class="com.itheima.dao.impl.BookDaoImpl" id="bookDao"></bean>

    <!-- 相当于 bookService = new BookServiceImpl() -->
    <bean class="com.itheima.service.impl.BookServiceImpl" id="bookService">
        <!--
            4、property标签: 调用set方法赋值
                name: 成员变量名, 对应set方法名,首字母大写
                ref: 对引用类型的成员变量赋值, 引用的对象
        -->
        <property name="bookDao" ref="bookDao"/>
    </bean>

</beans>

6、第六步:测试

package com.itheima.service.impl;

import com.itheima.dao.BookDao;
//import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;

public class BookServiceImpl implements BookService {
    // 1、第一步:删除以下代码,定义私有属性不初始化
    // private BookDao bookDao = new BookDaoImpl();
    private BookDao bookDao;

    // 2、第二步:提供set方法
    // alt+insert
    public void setBookDao(BookDao bookDao) {
        System.out.println("BookServiceImpl 使用setBookDao给成员变量赋值");
        this.bookDao = bookDao;
    }

    public void save() {
        System.out.println("bookService 保存数据");
        bookDao.save();
    }
}
  • ==效果==:

image-20231026145825596.png

5.4 property标签

  • 作用:调用 set 方法赋值
  • name 属性:成员变量名,对应 set 方法名,首字母大写
  • ref 属性:对引用类型的成员变量赋值,引用的对象

5.5 小结

1.什么是 DI

  • 在容器中建立 beanbean 之间的依赖关系的整个过程,称为依赖注入
  • Service 对象是一个 beanDao 对象是一个 BeanService 里面使用了 Dao,就说明 Service 依赖了 Dao 对象
  • 对于如何给 Service 中的 Dao 对象赋值,DI 可以从 IOC 容器中获取对应的 bean 对象并赋值,达到了 IOC 容器中的对象重用

2.为什么使用 DI(Dependency Injection)依赖注入?有什么好处?

  • 代码解耦性更强,更容易扩展系统

image-20231026151344336.png

  1. DI 实现步骤:以 Service 对象中依赖 Dao 对象的赋值为例

image-20231026151445291.png

  1. 依赖注入需要在类中添加什么方法?
    • 答:属性 set 方法
  2. 依赖注入需要在配置文件中添加什么元素?
    • 答:property 标签

6.bean的配置

6.1 学习内容

  • 基础配置
  • bean 作用范围
  • 生命周期

6.2 bean标签语法

image-20231026152423247.png

6.3 bean别名配置

image-20231026152719874.png

==注意事项==:

  • 获取 bean 无论是通过 id 还是 name 获取,如果无法获取到,将抛出异常 NoSuchBeanDefinitionException,即 NoSuchBeanDefinitionException: No bean named 'bookServiceImpl' available

6.4 bean别名配置:示例

1、第一步:创建项目

  • 新建 03_spring_bean 项目

2、第二步:添加依赖

  • 修改 pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>03_spring_bean</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>
        <!-- 1、spring核心依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <!-- 2、测试依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3、第三步:数据层

  • 定义 dao 层接口:
package com.itheima.dao;

public interface BookDao {
    void save();
}
  • 定义 dao 层实现类:
package com.itheima.dao.impl;

import com.itheima.dao.BookDao;

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save");
    }
}

4、第四步:业务层

  • 定义 service 层接口:
package com.itheima.service;

public interface BookService {
    void save();
}
  • 定义 service 层实现类:
package com.itheima.service.impl;

import com.itheima.dao.BookDao;
//import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;

public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public void save() {
        bookDao.save();
    }
}

5、第五步:定义配置

  • 新建 application.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">


    <!--
        1、name属性:可以设置多个别名,别名之间使用逗号,空格,分号等分隔
        2、注意:id只能设置一个,并且id的值要唯一。name可以设置多个
    -->

    
    <!-- 相当于 bookDao = new BookDaoImpl() -->
    <bean class="com.itheima.dao.impl.BookDaoImpl" id="bookDao"></bean>

    <!-- 相当于 bookService = new BookServiceImpl() -->
    <!-- 3、name: bean的别名 -->
    <bean class="com.itheima.service.impl.BookServiceImpl"
          id="bookService"
          name="a1 b1 c1">
        <property name="bookDao" ref="bookDao"/>
    </bean>

</beans>

6、第六步:测试

package test;

import com.itheima.service.BookService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BookTest {
    @Test
    public void testGetBean() {
        // 1. 让Spring去解析application.xml,使用IoC容器创建Bean
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

        // 2. 从IoC容器中获取Bean
        // 通过 name 别名获取bean对象
        BookService bookService = (BookService) context.getBean("a1");
        System.out.println("bookService = " + bookService);
        // 通过 name 别名获取bean对象
        bookService = (BookService) context.getBean("b1");
        System.out.println("bookService = " + bookService);
        // 通过 name 别名获取bean对象
        bookService = (BookService) context.getBean("c1");
        System.out.println("bookService = " + bookService);

        // 3. 关闭IoC容器
        context.close();
    }
}
  • ==效果==:

image-20231026154842152.png

6.5 bean作用范围

1、语法

image-20231026160949897.png

==补充==:

  • request:仅适用于 Web 环境下的 ApplicationContext,每一个 Http 请求都会拥有一个单独的实例
  • session:仅适用于 Web 环境下的 ApplicationContext,即每一个用户都将拥有一个单独的实例
  • globalSession:仅适用于 Web 环境下的 ApplicationContext,表示每一个全局的 Http Session 下都会拥有一个单独的实例

2、说明

  • 适合交给容器进行管理的bean
    • 控制器对象 (以前用的Servlet做为控制器)
    • 业务层对象 (如:BookService)
    • 数据层对象 (如:BookDao或BookMapper)
    • 工具对象 (如:CartUtils对象)
  • 不适合交给容器进行管理的bean
    • 封装实体的域对象(实体类对象 Book 包名:pojo,entity, domain)
    • 实体类对象一般是mybatis查询数据库得到结果,需要根据每一次结果创建对象

6.6 bean作用范围:示例

1、第一步:创建项目

  • 新建 04_spring_bean_scope 项目

2、第二步:添加依赖

  • 修改 pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>04_spring_bean_scope</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>
        <!-- 1、spring核心依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <!-- 2、测试依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
</project>

3、第三步:数据层

  • 定义 dao 层接口:
package com.itheima.dao;

public interface BookDao {
    void save();
}
  • 定义 dao 层实现类:
package com.itheima.dao.impl;

import com.itheima.dao.BookDao;

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save");
    }
}

4、第四步:业务层

  • 定义 service 层接口:
package com.itheima.service;

public interface BookService {
    void save();
}
  • 定义 service 层实现类:
package com.itheima.service.impl;

import com.itheima.dao.BookDao;
//import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;

public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public void save() {
        bookDao.save();
    }
}

5、第五步:定义配置

  • 新建 application.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">


    <!--
        1、scope属性:定义bean的作用范围,一共有5个
             singleton: 设置单例创建对象(推荐,也是默认值),好处:节省资源   IOC容器创建的时候创建   线程不安全,需要枷锁
             prototype: 设置多例创建对象,每次从IOC容器获取的时候都会创建新的对象,获取多次创建多次
             request: 在web开发环境中,IOC容器会将对象放到request请求域中,对象存活的范围在一次请求内
                      请求开始创建对象,请求结束销毁对象
             session: 在web开发环境中,IOC容器会将对象放到session会话域中,对象存活的范围在一次会话内
                      会话开始开始创建对象,会话销毁对象销毁
             global-session: 是多台服务器共享同一个会话存储的数据
             【面试题】请你说出spring的Bean作用域有什么?分别有什么作用?
    -->


    <!-- 相当于 bookDao = new BookDaoImpl() -->
    <bean class="com.itheima.dao.impl.BookDaoImpl" id="bookDao"></bean>

    <!-- 相当于 bookService = new BookServiceImpl() -->
    <!--  2、scope: bean的作用范围, 默认是singleton单例, prototype多例,每次获取都是新的对象 -->
    <bean class="com.itheima.service.impl.BookServiceImpl"
          id="bookService"
          name="a1 b1 c1"
          scope="singleton">
        <property name="bookDao" ref="bookDao"/>
    </bean>

</beans>

6、第六步:测试

package test;

import com.itheima.service.BookService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BookTest {
    @Test
    public void testGetBean() {
        // 1. 让Spring去解析application.xml,使用IoC容器创建Bean
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

        // 2. 从IoC容器中获取Bean
        // 验证是否是单例的
        BookService bookService = (BookService) context.getBean("bookService");
        System.out.println("bookService = " + bookService);
        BookService bookService1 = (BookService) context.getBean("bookService");
        System.out.println("bookService1 = " + bookService1);
        BookService bookService2 = (BookService) context.getBean("bookService");
        System.out.println("bookService2 = " + bookService2);

        // 3. 关闭IoC容器
        context.close();
    }
}
  • ==效果==:

image-20231026162619220.png

7、小结

  • 默认是 singleton 单例
  • 如果设置 prototype 多例,则每次获取都是新的对象

6.7 bean生命周期

1、概念

  • 生命周期:从创建到消亡的完整过程
  • bean 生命周期:bean 从创建到销毁的整体过程
  • bean 生命周期控制:在 bean 创建后到销毁前做一些事情

2、bean生命周期控制

image-20231026163828590.png

3、过程

  • 初始化容器
    • 创建对象(内存分配)
    • 执行构造方法
    • 执行属性注入(set 操作)
    • 执行 bean 初始化方法
  • 使用 bean
    • 执行业务操作
  • 关闭/销毁容器
    • 执行 bean 销毁方法(单例模式下才执行销毁方法)

4、bean销毁时机

  • 容器关闭前触发 bean 的销毁

  • 关闭容器方式:

    • 手工关闭容器:close() 操作

    • 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机:registerShutdownHook() 操作

image-20231026164117459.png

6.8 bean生命周期:示例

1、第一步:创建项目

  • 新建 05_spring_bean_life 项目

2、第二步:添加依赖

  • 修改 pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>05_spring_bean_life</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>



    <dependencies>
        <!-- 1、spring核心依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <!-- 2、测试依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
</project>

3、第三步:数据层

  • 定义 dao 层接口:
package com.itheima.dao;

public interface BookDao {
    void save();
}
  • 定义 dao 层实现类:
package com.itheima.dao.impl;

import com.itheima.dao.BookDao;

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save");
    }
}

4、第四步:业务层

  • 定义 service 层接口:
package com.itheima.service;

public interface BookService {
    void save();
}
  • 定义 service 层实现类:
package com.itheima.service.impl;

import com.itheima.dao.BookDao;
//import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;

public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    // 1、无参构造方法
    public BookServiceImpl() {
        System.out.println("BookServiceImpl 无参构造器");
    }
    
    // 2、setter方法
    public void setBookDao(BookDao bookDao) {
        System.out.println("BookServiceImpl 使用setBookDao给成员变量赋值");
        this.bookDao = bookDao;
    }

    public void save() {
        bookDao.save();
    }

    // 3、初始化方法
    public void init() {
        System.out.println("BookServiceImpl 执行初始化啦!");
    }

    // 4、销毁方法
    public void destory() {
        System.out.println("BookServiceImpl 销毁啦!");
    }
}

5、第五步:定义配置

  • 新建 application.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">


    <!--
        1、目标:创建BookServiceImpl对象,设置生命周期方法
            init-method="init" 在对象创建后立即调用初始化方法
            destroy-method="destroy":在容器执行销毁前立即调用销毁的方法
        2、注意:只有单例对象才会运行销毁生命周期方法
    -->

    
    <bean class="com.itheima.dao.impl.BookDaoImpl" id="bookDao"></bean>
    
    <!--
        3、init-method: 对象初始化方法
        4、destroy-method: 对象销毁的方法, 如果是多例,不会执行销毁方法
    -->
    <bean class="com.itheima.service.impl.BookServiceImpl"
          id="bookService"
          name="a1 b1 c1"
          scope="singleton"
          init-method="init"
          destroy-method="destory">
        <property name="bookDao" ref="bookDao"/>
    </bean>


</beans>

6、第六步:测试

package test;

import com.itheima.service.BookService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BookTest {
    @Test
    public void testGetBean() {
        // 1. 让Spring去解析application.xml,使用IoC容器创建Bean
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

        // 2. 从IoC容器中获取Bean
        // 验证是否是单例的
        BookService bookService = (BookService) context.getBean("bookService");
        System.out.println("bookService = " + bookService);

        // 3. 调用对象的方法
        bookService.save();

        // 4. 关闭IoC容器
        context.close();
    }
}
  • ==效果==:

image-20231026170431997.png

7、小结

  1. bean 生命周期过程

    • 创建对象(内存分配)
    • 创建对象,执行构造方法:new BookServiceImpl()
    • 执行属性注入(set 操作):依赖注入
    • 执行初始化方法
    • 业务
    • 销毁方法:容器关闭或者销毁前调用(注意:销毁方法只在单例模式中生效)
  2. bean 生命周期控制

    • init-method
    • destroy-method

image-20231026171004783.png

  1. 关闭容器

    • close()

    • registerShutdownHook()

8、联系方式

  • 文章如果侵权请联系删除,谢谢
  • 交流:1326733085