Bean作用域及生命周期

news2025/2/27 10:29:48

关于Bean对象,在将其存储到spring中以后,在使用或读取该Bean对象时,如果该对象是公有的,难免就会出现被一方修改,从而影响另外一方读取到的对象准确性的情况。因此了解Bean的作用域和生命周期就是十分必要的了。

首先,还是具体使用一个例子来理解上面提到的这种情况:

文章目录

    • 示例
    • Bean的6种作用域
      • singleton
      • prototype
      • request
      • session
      • application
      • websocket
    • Bean作用域的设置
    • Spring的执行流程
    • Bean生命周期

示例

首先,新建一个Student实体类,为其设置属性,并提供其相关的get/set方法;

package com.yun.model;

public class Student {
    private int id;
    private String name;
    private double score;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}

创建一个Bean对象,使用方法注解存储到Spring;

package com.yun.controller;

import com.yun.model.Student;
import com.yun.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class StudentBean {

    @Bean
    public Student stu(){
        Student student=new Student();
        student.setId(5);
        student.setName("李大锤");
        student.setScore(99.6);
        return student;
    }
}

A首先读取并且使用bean,同时进行一定的操作;

package com.yun.controller;

import com.yun.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/*
* A     1.获取bean;
*       2.创建了新的对象,对新创建的对象进行修改
* */
@Controller
public class StuController1 {
    @Autowired

    private Student student1;

    public Student getStu1(){
        Student student=student1;

        System.out.println("student1 id="+student.getId()+" name="+student.getName());
        student.setId(10);
        student.setName("安慕希");
        return student;

    }
}

B 读取bean;

package com.yun.controller;

import com.yun.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/*
* B 读取bean,获取bean的具体值
* */
@Controller
public class StuController2 {
    @Autowired
    private Student student1;

    public Student getStud2(){
        Student student=student1;
        return student;
    }
}

获取原始bean的值,以及A读取到的值和B读取到的值;

在这里插入图片描述
通过运行结果可以得到结论,尽管看起来A是在自己新创建的Bean对象上进行了修改,但最终还是会影响到原始公共Bean的值;

而究其出现这种结果的原因,其实就是因为Bean在默认情况下是单例模式,即只有一份对象,这份对象供所有访问者使用。因此,A进行的修改操作自然也就会影响到B的读取结果。而使用单例状态的原因就是,提高性能。

Bean的6种作用域

作用域,顾名思义就是“作用到的区域或范围”,实际就是程序中变量的一个可用的范围。而Bean的作用域其实就是Bean在Spring框架中的某种行为模式,具体共有6种:

  • singleton:单例作⽤域
  • prototype:原型作⽤域(多例作⽤域)
  • request:请求作⽤域
  • session:会话作⽤域
  • application:全局作⽤域
  • websocket:HTTP WebSocket 作⽤域

singleton

是Spring默认选择的作用域;
在此作用域下的Bean在IoC容器中只有一个实例,即只有一个全局对象;
通常当Bean对象的属性状态不需要更新时,即Bean无状态的情况下会使用该作用域;

prototype

多例模式下使用的作用域;
在此作用域下的Bean每被访问一次就会创建出一个实例;
通常当Bean对象的属性状态需要更新时,即Bean有状态的情况下会使用该作用域;

在普通的Spring项目中,一般只有前面两种作用域;而后面提到的作用域则是只能在SpringMVC中使用或只能在Spring WebSocket中使⽤;

request

在每次http请求时都会创建一个新的Bean的实例;
只能在SpringMVC中使用;

session

每次会话都会定义一个Bean的实例;
只能在SpringMVC中使用;

application

在一个http servlet Context中,共享一个Bean实例;
只能在SpringMVC中使用;

websocket

在一个HTTP WebSocket中,定义一个Bean实例同时共享这个实例;
只能在Spring WebSocket中使⽤;

Bean作用域的设置

由于我们这里主要介绍的是Spring项目,因此关于Bean作用域的设置也只涉及到两种;

singleton是Spring默认的作用域,因此一个新创建的bean对象在不进行特别设置的情况下,其作用域就是singleton;

下面具体演示prototype的设置:

在这里插入图片描述

prototype的设置有上面图片中所示的两种方式,我们也可以从相关类中找到该作用域的定义信息:
在这里插入图片描述
在为其设置了全局作用域后,我们再次执行文章开始的实例,得到的结果如下:
在这里插入图片描述
此时,A的修改操作不再影响到B的读取;

Spring的执行流程

  1. 启动容器;

在这里插入图片描述
首先,启动容器,去加载相关的配置文件;

  1. 进行Bean初始化

在这里插入图片描述

对配置了加载组件路径下的类进行扫描,即扫描该路径下的文件,查看是否有相关的类注解;

  1. 注册Bean对象到容器
    在这里插入图片描述

将在加载组件路径下的类中,添加了相关注解的类注册到容器中;

  1. 装配或使用Bean

在这里插入图片描述
即将需要使用的Bean注入到需要的类中去;

  1. Spring销毁

相关使用操作完毕,最终Spring销毁;

Bean生命周期

生命周期实际就是一个对象从产生到被销毁的全过程,关于Bean生命周期主要有5步:

  1. 实例化Bean

即为Bean对象分配内存空间;

  1. 设置属性
    对Bean对象进行依赖注入;
  2. 进行Bean初始化
    3.1 执行各种通知;

3.2 初始化的前置方法;

3.3 初始化方法;
3.4 初始化的后置方法;

  1. 使用Bean;
  2. 销毁Bean;

简单使用代码来观察这个过程:

package com.yun.controller;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class BeanLife implements  BeanNameAware {



    @Override
    public void setBeanName(String s) {

        System.out.println("执行 setBeanName() 通知 "+s);
    }


    @PostConstruct
    public void myPostConstruct(){
        System.out.println("执行 myPostConstruct() 方法");
    }



    public void init(){
        System.out.println("执行 init()");
    }

    public void use(){
        System.out.println("执行 use 方法");
    }

    @PreDestroy
    public void myPreDestroy(){
        System.out.println("执行 myPreDestroy() 销毁");
    }
}

使用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:content="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">

<!--    <bean id="userService" class="com.bit.service.UserService"></bean>-->



    <!-- 配置存储 Bean 对象的扫描根路径 -->
    <content:component-scan base-package="com.yun"></content:component-scan>

    <bean id="beanlife" class="com.yun.controller.BeanLife"
          init-method="init"></bean>


</beans>

设置一个启动类:

import com.yun.controller.BeanLife;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifeApp {
    public static void main(String[] args) {
        
        /*
        * 必须使用ClassPathXmlApplicationContext类,ApplicationContext无方法destroy()方法
        * */
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        BeanLife beanLife=context.getBean("beanlife",BeanLife.class);
        beanLife.use();
        System.out.println("执行 main方法");
        context.destroy();
    }
}

运行结果:

在这里插入图片描述

over!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1382756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一、MySQL 卸载

目录 1、软件的卸载准备 2、软件的卸载 方式一&#xff1a;通过控制面板卸载 方式二&#xff1a;通过mysql8的安装向导卸载 1、双击mysql8的安装向导 2、取消更新 3、选择要卸载的mysql服务器软件的具体版本 4、确认删除数据目录 5、执行删除 6、完成删除 3、清理残…

Springboot中使用Filter过滤器

1、概述 springboot工程中使用Filter过滤器与其他地方使用基本相同&#xff0c;只是注入的方式不同。 2、创建Filter过滤器 实现Filter接口&#xff0c;重写doFilter方法 filterChain.doFilter(servletRequest,servletResponse);表示放行 public class MyFilter implement…

Python字符串验证与正则表达式【第23篇—python基础】

文章目录 引言方法1&#xff1a;使用 isalpha() 方法方法2&#xff1a;使用正则表达式方法3&#xff1a;遍历字符检查应用场景示例与比较优化与扩展方法4&#xff1a;考虑空格和其他字符应用场景扩展 示例与比较优化与扩展方法4&#xff1a;考虑空格和其他字符方法5&#xff1a…

Linux下通过EDAC功能检测PCIE硬件错误

1 EDAC的作用 The edac kernel modules goal is to detect and report hardware errors that occur within the computer system running under linux. 《Documentation/admin-guide/ras.rst》 EDAC可以检测物理内存的错误 和 PCIE的错误&#xff0c;本文主要分析后者。 2 机…

简单的天天酷跑小游戏实现

初级函数实现人物,背景,小乌龟的移动 #include <graphics.h> #include <iostream> #include <Windows.h> #include "tools.h" #include <mmsystem.h> #include <conio.h> #include <time.h>//时间头文件 #include <cstdlib&g…

散列函数,哈希表hash table

附上一句话&#xff1a;我知道大家可能曾经了解过这个散列表了&#xff0c;我发现&#xff0c;如果多看几个相关的视频&#xff0c;从不同的表述方式和不同的理解角度来理解这个问题&#xff0c;我会明白的更透彻&#xff0c;也有更多新的收获&#xff0c;尤其是对这个算法的应…

ES 之索引和文档

本文主要介绍ES中的数据组成结构单元。 一、文档(Document) 1、概念 ES的数据存储单元是面向文档的&#xff0c;文档是所有数据存储&#xff0c;搜索的最小单元。 你可以把ES中的文档对应成mysql中的一条条数据记录。到时候你存进ES的数据就是一个个文档。 文档存入ES是序列…

时序预测 | MATLAB实现GRNN广义回归神经网络时间序列未来多步预测(程序含详细预测步骤)

时序预测 | MATLAB实现GRNN广义回归神经网络时间序列未来多步预测(程序含详细预测步骤) 目录 时序预测 | MATLAB实现GRNN广义回归神经网络时间序列未来多步预测(程序含详细预测步骤)预测效果基本介绍程序设计参考资料预测效果 基本介绍 MATLAB实现GRNN广义回归神经网络时间序列…

利用GraalVM将java文件变成exe可执行文件

上期文章已经配置好了环境&#xff1a;Springboot3新特性&#xff1a;开发第一个 GraalVM 本机应用程序(完整教程)-CSDN博客 在桌面上创建一个HelloWorld.java的文件。 public class HelloWorld{public static void main (String[] args){System.out.println("Hello,Wor…

二叉树及其实现

二叉树 一.树的概念及结构1.1树的概念1.2相关概念 2.二叉树的概念及结构2.1 概念2.2 特殊的二叉树 3.二叉树的遍历3.1 前序、中序以及后序遍历3.2 层序遍历3.3 判断二叉树是否是完全二叉树3.4 二叉树的高度3.5 二叉树的叶子节点个数3.6 二叉树的第k层的节点个数3.7 二叉树销毁3…

行为型设计模式——命令模式

命令模式 日常生活中&#xff0c;我们出去吃饭都会遇到下面的场景。 定义&#xff1a; 将一个请求封装为一个对象&#xff0c;使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通&#xff0c;这样方便将命令对象进行存储、传递、调用、增加与管理。命…

【进程调度】基于优先级的轮转调度C++实现算法

一、简介 1.1 背景 在计算机科学领域&#xff0c;进程调度是操作系统中一个关键的组成部分&#xff0c;它负责协调系统中各个进程的执行顺序&#xff0c;以最大程度地提高系统资源利用率。在这篇博客中&#xff0c;将深入探讨基于优先级的轮转调度算法&#xff0c;该算法结合…

小白浅学Vue3

目录 前端环境 依赖管理NPM安装配置 创建Vue项目 模板语法 文本插值{{ }} v-html 属性绑定 条件渲染 v-if 、v-else-if 、v-else v-show 列表渲染v-for 状态管理 事件 事件 事件传参 事件修饰符 数组变化监听 计算属性 Class绑定 Style绑定 侦听器 v-mod…

Fastadmin上传图片服务端压缩图片,实测13.45M压缩为29.91K

先前条件&#xff1a;第一步安装compose&#xff0c;已安装忽略。 先上截图看效果 一、在fastadmin的根目录里面输入命令安装think-image composer require topthink/think-image二、找到公共上传类&#xff0c;application/common/library/Upload.php&#xff0c;在最下面…

【数据结构与算法】之数组系列-20240113

这里写目录标题 一、66. 加一二、121. 买卖股票的最佳时机三、136. 只出现一次的数字四、268. 丢失的数字五、350. 两个数组的交集 II 一、66. 加一 简单 给定一个由 整数 组成的 非空 数组所表示的非负整数&#xff0c;在该数的基础上加一。 最高位数字存放在数组的首位&…

七:Day08_任务调度

第一章 定时任务概述 在项目中开发定时任务应该一种比较常见的需求&#xff0c;在 Java 中开发定时任务主要有三种解决方案&#xff1a;一是使用JDK 自带的 Timer&#xff0c;二是使用 Spring Task&#xff0c;三是使用第三方组件 Quartz。 建议&#xff1a; 单体项目架构使用…

Linux系统——远程访问及控制

目录 一、OpenSSH服务器 1.SSH&#xff08;Secure Shell&#xff09;协议 2.OpenSSH 2.SSH原理 2.1公钥传输原理 2.2加密原理 &#xff08;1&#xff09;对称加密 &#xff08;2&#xff09;非对称加密 2.3远程登录 2.3.1延伸 2.3.2登录用户 3.SSH格式及选项 3.1延…

K8s-Pod资源(一)Pod介绍、创建Pod、Pod简单资源配额

Pod概述 Kubernetes Pod | Kubernetes Pod是Kubernetes中的最小调度单元&#xff0c;k8s都是以pod的方式运行服务的 一个pod可以指定镜像&#xff0c;封装一个或多个容器 pod需要调度到工作节点运行&#xff0c;节点的选择由scheduler调度器实现 pod定义时&#xff0c;会…

【Python学习】Python学习17- File(文件) 方法

目录 [TOC](【Python学习】Python学习17- File(文件) 方法) 文章所属专区 Python学习 前言 本章节主要说明Python文件操作的具体说明 open()方法 Python open() 方法用于打开一个文件&#xff0c;并返回文件对象&#xff0c;在对文件进行处理过程都需要使用到这个函数&#…

C++ QtCreator启动执行报错的各类问题解决++持续更新!!

1.QTCreator启动报错"由于找不到 python310.dll" 在QtCreator加载自动缩进的LLVM插件后, 再次打开Qt时, 会报错找不到python310.dll 解决方法&#xff1a;下载python310.dll,随后复制到目录&#xff1a;C:\Program Files\LLVM\bin 即可解决该问题。下载路径附件如…