Bean作用域及生命周期

关于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;}@Overridepublic 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 {@Beanpublic 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 {@Autowiredprivate 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 {@Autowiredprivate 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 {@Overridepublic void setBeanName(String s) {System.out.println("执行 setBeanName() 通知 "+s);}@PostConstructpublic void myPostConstruct(){System.out.println("执行 myPostConstruct() 方法");}public void init(){System.out.println("执行 init()");}public void use(){System.out.println("执行 use 方法");}@PreDestroypublic 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.mzph.cn/news/618892.shtml

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

相关文章

Fedora Linux 中安装 nginx

Fedora 35 中安装 nginx 的方法非常简单。 运行下面的命令&#xff1a; sudo dnf install nginx 在提示你需要确认的地方&#xff0c;输入 y 后回车即可。 开机自动启动 如果你希望在你的操作系统重启的时候自动启动 nginx&#xff0c;请输入下面的命令&#xff1a; syst…

【昕宝爸爸小模块】如何让Java的线程池顺序执行任务

➡️博客首页 https://blog.csdn.net/Java_Yangxiaoyuan 欢迎优秀的你&#x1f44d;点赞、&#x1f5c2;️收藏、加❤️关注哦。 本文章CSDN首发&#xff0c;欢迎转载&#xff0c;要注明出处哦&#xff01; 先感谢优秀的你能认真的看完本文&…

文本翻译GUI程序,实现简单的英汉互译

项目地址&#xff1a;mendianyu/txtTranslate: 文本翻译GUI程序&#xff0c;实现简单的英汉互译 (github.com) 文本翻译GUI程序&#xff0c;实现简单的英汉互译 项目结构 三个java文件加一个pom文件 项目运行效果 语言可选择en(英语) zh(汉语) auto(自动识别&#xff0c;仅源语…

序章 熟悉战场篇—了解vue的基本操作

了解vue 的基本目录&#xff1a; dist 是打包后存放的目录(后续可以改)node_modules 是依赖包public 是静态index页面src 是存放文件的目录assets 是存放静态资源的目录components 是存放组件的目录views 是存放页面文件的目录&#xff08;没有views 自己新建一个&#xff09;A…

使用FreeBASIC设计8051单片机汇编编译器

在STC论坛上看到有人用C语言实现8051汇编编译器&#xff08;源码&#xff09;&#xff0c;好奇下&#xff0c;试着用FB写了一下。 基本原理就是通过分析汇编文件然后转换为机器码。以下是51汇编与机器码对应的表格&#xff08;数据来自网络&#xff0c;如果发现有误请联系QQ149…

【InternLM 大模型实战】第四课

XTuner 大模型单卡低成本微调实战 FINETUNE简介指令跟随微调增量预训练微调LoRA & QLoRA XTuner简介功能亮点适配多种生态适配多种硬件 8GB 显卡玩转LLMFlash AttentionDeepSpeed ZeRO 动手实战环节环境配置微调准备配置文件模型下载数据集下载修改配置文件开始微调将得到的…

HTML标签(一)

目录 HTML语法规范 基本语法概述 标签关系 HTML基本结构标签 第一个HTML网页 开发工具 VSCode的使用&#xff1a; VScode工具生成骨架标签新增代码 文档类型声明标签 lang语言种类 字符集 总结 HTML常用标签 标签语义 标题标签 段落标签 换行标签 文本格式化…

unity urp 视差卡牌

总体效果大概四层&#xff0c;从后往前排序为&#xff1a;卡背、背景、画像、边框 首先卡背比较简单&#xff0c;只要判断如果网格的背面就直接采样卡背图片展示即可 资源准备&#xff1a; 然后是背景&#xff0c;网上找到一张这样的图。 但他还不符合要求&#xff0c;我们的…

Tomcat源码解析(一): Tomcat整体架构

Tomcat源码系列文章 Tomcat源码解析(一)&#xff1a; Tomcat整体架构 目录 一、Tomcat整体架构1、Tomcat两个核心组件功能2、Tomcat支持的多种I/O模型和应用层协议 二、Connector连接器1、连接器功能汇总2、ProtocolHandler组件2.1、Endpoint2.2、Processor 3、Adapter组件 三…

好大夫问诊数据爬虫记录

好大夫问诊数据爬虫入库字段记录 获取医生的病程列表 uid Column(Integer, primary_keyTrue, autoincrementTrue) gender Column(String(10)) # 性别 age Column(Integer) # 年龄 # 总交流次数 total_communication_times Column(Integer) # 医生回复次数 doctor_reply_t…

uniapp 编译后文字乱码的解决方案

问题: 新建的页面中编写代码&#xff0c;其中数字和图片都可以正常显示&#xff0c;只有中文编译后展示乱码 页面展示也是乱码 解决方案: 打开HuilderX编辑器的【文件】- 【以指定编码重新打开】- 【选择UTF-8】 然后重新编译就可以啦~ 希望可以帮到你啊~

2023极客大挑战web小记

拿到题目提示post传参还以为是道签到题 刚开始直接把自己极客大挑战的username以及password怼上去&#xff0c;但是不对。看看F12&#xff0c;有提示。 当一个搜索蜘蛛访问一个站点时&#xff0c;它会首先检查该站点根目录下是否存在robots.txt&#xff0c;如果存在&#xff0c…

部署Tomcat及其负载均衡

Tomcat服务器是一个免费的开放源代码的Web应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP程序的首选。一般来说&#xff0c;Tomcat虽然和Apache或者Nginx这些Web服务器一样&#xf…

CSS 下载进度条

<template><view class=btn>下载中</view></template><script></script><style>/* 设置整个页面的样式 */body {width: 100vw; /* 页面宽度为视口宽度 */background: #000000; /* 背景颜色为白色 */display: flex; /* 使用 flex…

linux GDB and GDB Sever

概念&#xff1a; GDB&#xff08;GNU Debugger&#xff09;是一个用于调试程序的强大工具。它是GNU项目的一部分&#xff0c;支持多种编程语言&#xff0c;包括C、C等。GDB 提供了一组命令和功能&#xff0c;允许跟踪检查程序的内部状态&#xff0c;跟踪代码的执行过程&#…

MySQL题目示例

文章目录 1.题目示例 1.题目示例 09&#xff09;查询学过「张三」老师授课的同学的信息 SELECT s.*, c.cname, t.tname, sc.score FROM t_mysql_teacher t, t_mysql_course c, t_mysql_student s, t_mysql_score sc WHERE t.tid c.tid AND c.cid sc.cid AND sc.sid s.sid …

一种具有轨迹优化的无人驾驶车实时运动规划器 论文阅读

论文题目&#xff1a;A Real-Time Motion Planner with Trajectory Optimization for Autonomous Vehicles Abstract 本文的实时规划器首先将空间离散化&#xff0c;然后基于一组成本函数搜索出最佳轨迹。迭代优化所得到的轨迹的Path和Speed。post-optimization计算复杂度低&…

TF-IDF(Term Frequency-Inverse Document Frequency)算法详解

目录 概述 术语解释 词频&#xff08;Term Frequency&#xff09; 文档频率&#xff08;Document Frequency&#xff09; 倒排文档频率&#xff08;Inverse Document Frequency&#xff09; 计算&#xff08;Computation&#xff09; 代码语法 代码展示 安装相关包 测…

邮件开发客户:从吸引潜在客户到提高转化率的实用指南

做外贸的很多企业都习惯使用邮件作为沟通工具&#xff0c;所以我们也可以利用邮件发送开发信来进行客户开发。 为什么外贸企业喜欢使用邮件呢&#xff1f; 1、使用习惯 不同于我们国家习惯使用微信沟通&#xff0c;邮件始终是外国人在进行商务、营销、日常沟通等场合下常用且重…

基于OCR的包装产品生产日期识别系统

基于OCR的包装产品生产日期识别系统 背景技术方案PaddleOCR模型应用数据挑战与解决方案优化策略 项目实施步骤结果与展望 背景 在工业生产中&#xff0c;产品包装上的生产日期信息是至关重要的&#xff0c;它关系到物资的时效性和质量。为了更快、更准确地提取这些信息&#x…