Spring初识(四)

news2025/1/11 4:19:31

文章目录

  • 前言
  • 一.Bean的作用域
    • 1.1 作用域例子
    • 1.2 Bean的作用域类型
  • 二.Bean的生命周期

前言

在前面我们学习了spring简单的读取和存储对象之后,Spring 中 Bean 是最核心的操作资源,我们接下来会介绍Bean对象.

一.Bean的作用域

什么是Bean作用域呢?
限定程序中变量的可用范围叫做作用域,或者说在源代码中定义变量的某个区域就叫做作用域。
而Bean 的作用域是指Bean 在 Spring整个框架中的某种行为模式.
我们具体用一个例子来说Bean的域.例子如下:

1.1 作用域例子

具体的场景如下:
假设现在有一个公共的Bean,提供给A用户和B用户使用,然而在使用的途中A用户却“悄悄"地修改了公共 Bean 的数据,导致B用户在使用时发生了预期之外的逻辑错误。
具体先看代码:
1.准备好具体的User类

public class User {
    private int id;
    private String name;

    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;
    }

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

2.把User存入spring容器中

@Component
public class UserBeans {
    @Bean
    public User user(){
        User user=new User();
        user.setId(11);
        user.setName("关羽");
        return user;
    }
}

3.这里有两个对象,分别对User对象做操作

对象一.

@Controller
public class UserController {
    @Autowired
    private User user;
    public void printUser(){
        System.out.println(user);
        //修改User
        User myUser=user;
        myUser.setName("张飞");
        System.out.println("myUser -> "+myUser);
        System.out.println("user ->"+user);
    }

}

对象二:

@Controller
public class UserController2 {
    @Resource
    private User user;
    public void printUser2(){
        System.out.println("user->"  +user);
    }
}

4.具体的操作

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
      UserController userController= context.getBean("userController",UserController.class);
        userController.printUser();
        UserController2 userController2=context.getBean("userController2",UserController2.class);
        userController2.printUser2();

    }
}

执行结果:
在这里插入图片描述

其实这里的预期结果,我们第二次读取的操作的时候,应该打印的还是关羽的信息,但是现在出现了,张飞.按照正常的执行流程,我们应该出现的是关羽的信息.
这就是因为Bean对象是有作用域的.下面介绍Bean的作用域

1.2 Bean的作用域类型

在Spring中,Bean的作用域类型决定了Bean的生命周期和在应用程序中的可见性。Spring框架支持以下几种常见的Bean作用域类型:

  1. Singleton(默认): 在整个应用程序中,只创建一个Bean实例。无论多少次请求该Bean,都返回同一个实例。这是Spring默认的作用域。可以通过@Scope(“singleton”)或者不添加@Scope注解来指定Singleton作用域。

  2. Prototype: 每次请求Bean时,都会创建一个新的实例。每次获取Bean时,都会返回一个不同的实例。可以通过@Scope(“prototype”)来指定Prototype作用域。

  3. Request: 每次HTTP请求都会创建一个新的Bean实例。在同一个请求中,多次获取Bean时都会返回同一个实例。通常用于Web应用程序中的每个请求,保证在同一个请求中的多次调用中都使用同一个Bean实例。可以通过@Scope(“request”)来指定Request作用域。

  4. Session: 每个HTTP Session都会创建一个新的Bean实例。在同一个Session中,多次获取Bean时都会返回同一个实例。通常用于Web应用程序中,保证在同一个Session中的多次调用中都使用同一个Bean实例。可以通过@Scope(“session”)来指定Session作用域。

  5. Application(仅适用于Web应用): 在整个Web应用中,只创建一个Bean实例。无论多少次请求该Bean,都返回同一个实例。通常用于Web应用程序中,保证在整个应用中都使用同一个Bean实例。可以通过@Scope(“application”)来指定Application作用域。

  6. WebSocket是一种在Web浏览器和服务器之间进行全双工通信的协议,允许实时、双向的数据传输。WebSocket的作用域主要涉及在Web应用程序中与其他部分的通信范围。

因此知道了这些作用域之后,我们回到上面的案例,我们要怎么才能达到我们的预期效果呢.
@Scope标签既可以修饰方法也可以修饰类,@Scope有两种设置方式:
1.直接设置值:@Scope(“prototype”)
2.使用枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
代码如下:

@Component
public class UserBeans {
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean
    public User user(){
        User user=new User();
        user.setId(11);
        user.setName("关羽");
        return user;
    }
}

执行结果:
在这里插入图片描述

最后我们来做一个简单的总结

1.单例模式: singleton(默认模式)>性能的考虑2.原型模式: prototype
3.请求作用域: request,每次 HTTP请求,都会创建一个Bean 对象。【适用于Spring MVC/Spring Web】4.会话作用域: session,每次Session会话共亨一个 Bean。【Spring MVC】
5.全局作用域: appli cation,一个http servlet context中共享一个bean。【Spring MVC】6.webscoket:网络长连接,只适用于Spring WebSocket项日。

二.Bean的生命周期

Bean的生命周期主要包括以下几个阶段:

  1. 开辟内存空间:实例化≠初始化
  2. 设置属性(注入属性)
  3. 初始化
    3.1各种通知
    3.2初始化前置方法
    3.3 初始化方法【两种实现方式: xml 方式、注解方式】
    3.4 初始化后置方法
  4. 使用Bean
  5. 销毁Bean 对象

让我们以一个生活中的例子来演示这样的流程:购买一台新的电视。

  1. 开辟内存空间(实例化): 当你购买一台新的电视时,实际上是在商店里买到了一台特定型号的电视,这时候可以认为你在购买电视的过程中已经开辟了一块内存空间,这个空间对应于新的电视对象。

  2. 设置属性(注入属性): 购买电视后,你将其搬回家并连接到电源和其他设备(例如DVD播放器、游戏机等),这个过程类似于将电视的属性值进行设置和注入。

  3. 初始化:

    各种通知: 开启电视后,它可能会显示欢迎信息或品牌标志,这是一种初始化阶段的通知。
    初始化前置方法: 在使用电视之前,你可能需要对电视进行一些设置,如调整屏幕亮度、音量等,这可以看作是初始化前置方法。
    初始化方法【两种实现方式:xml方式、注解方式】: 电视可以具有不同型号和功能,而对应于不同型号和功能,它们可能需要在初始化阶段进行不同的操作。例如,一些电视型号可能需要连接网络、搜索频道,这些可以通过在电视对象上调用初始化方法来实现。在Spring中,初始化方法可以通过在Bean定义中使用init-method属性或在Bean类上使用@PostConstruct注解来指定。
    初始化后置方法: 在初始化阶段完成后,电视可以显示出预设频道或导航界面,这可以看作是初始化后置方法。

  4. 使用电视(使用Bean): 一旦电视初始化完成并连接好,你可以开始使用它来观看电视节目、播放DVD或玩游戏,这是电视被使用的阶段。

  5. 销毁电视(销毁Bean对象): 长期使用后,如果你决定不再使用这台电视,或者它出现了故障,你可能会将其处理掉或退还给商店。这个过程类似于销毁Bean对象,在Spring中,销毁Bean对象可以通过在Bean定义中使用destroy-method属性或在Bean类上使用@PreDestroy注解来指定。

综上所述,购买一台新的电视可以类比为Bean的生命周期。在整个过程中,我们可以类比内存空间的开辟(实例化)、设置电视的属性(注入属性)、电视的初始化阶段(包括各种通知、初始化前置方法、初始化方法和初始化后置方法)、使用电视(使用Bean)、销毁电视(销毁Bean对象)等。

然后用一个代码的例子说明:
代码如下:

package com.java.demo.component;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.BeanPostProcessor;

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

public class BeanCompont implements BeanNameAware, BeanPostProcessor {
    @Override
    public void setBeanName(String s) {
        System.out.println("执行了通知 BeanName -> " + s);
    }

    /**
     * xml 方式的初始化方法
     */
    public void myInit() {
        System.out.println("XML 方式初始化");
    }

    @PostConstruct
    public void doPostConstruct() {
        System.out.println("注解初始化方法");
    }

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

    @PreDestroy
    public void doPreDestroy() {
        System.out.println("do PreDestroy");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("do postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("do postProcessAfterInitialization");
        return bean;
    }
}

具体执行:

   ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        BeanCompont compont = context.getBean("beanCompont", BeanCompont.class);
        compont.sayHi();
        context.destroy();

执行结果:
在这里插入图片描述

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

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

相关文章

[DDPM] Denoising Diffusion Probabilistic Models

直接看paper云里雾里,一些推荐的讲解: The Annotated Diffusion Model 生成扩散模型漫谈(一):DDPM 拆楼 建楼 生成扩散模型漫谈(二):DDPM 自回归式VAE 生成扩散模型漫谈&#xff…

SQL-每日一题【619.只出现一次的最大数字】

题目 MyNumbers 表: 单一数字 是在 MyNumbers 表中只出现一次的数字。 请你编写一个 SQL 查询来报告最大的 单一数字 。如果不存在 单一数字 ,查询需报告 null 。 查询结果如下例所示。 示例 1: 示例 2: 解题思路 1.题目要求我…

MyBatis---多表查询,动态sql的详细介绍

目录 1.命名规则 1.resultMap(对应类属性名称与数据库字段名称) 2.多表查询(ResultMap) 1.创建articleInfo类 2.创建ArticleMapper.xml配置文件和ArticleMapper接口 ①:不建议使用 (文件之间耦合严重…

十大排序算法详解

目录 1. 冒泡排序 a. 思路 b. code 2. 插入排序 a. 思路 b. code 3. 希尔排序【插入排序plus】 a. 思路 b. code 4. 选择排序 a. 思路 b. code 5. 基数排序 a. 前置知识 b. 思路 c. code 6. 计数排序 a. 思路 b. code 7. 桶排序(计数排序plus &…

怎么在shell中查看python版本以及降低anaconda的python版本

输入命令 python --version 电脑anaconda的python版本为3.11,如何降低版本 ,输入命令 conda install python3.9 当安装完anaconda后,ubuntu系统的shell命令行最前面会出现base字样,此时要退出,就输入命令 conda deacti…

如何开启QQ邮件的SMTP服务以及如何使用Python发送邮件

如何开启QQ邮件的SMTP服务以及如何使用Python发送邮件 😇博主简介:我是一名正在攻读研究生学位的人工智能专业学生,我可以为计算机、人工智能相关本科生和研究生提供排忧解惑的服务。如果您有任何问题或困惑,欢迎随时来交流哦&…

Qt应用开发——Drag and Drop

目录 一、前言 二、相关事件和类 三、实例 拖动文件到编辑框 一、前言 在实际场景中,经常会有导入文件的需求。导入文件一般两种方式,第一种QFileDialog显示一个文件选择窗口,选择后处理和显示。第二种就是使用拖放机制实现。还有在一些制…

.faust加密勒索数据库恢复---惜分飞

有客户的win服务器被勒索病毒加密,里面运行有用友系统的Oracle数据库,加密提示为(camry2020aol.com): 加密的数据文件类似(.DBF.id[0E564ACA-3493].[camry2020aol.com].faust): 通过工具检测发现少量bl…

(2)前端控制器的扩展配置, 视图解析器类型以及MVC执行流程的概述

SpringMVC入门程序的扩展说明 注册前端控制器的细节 在web.xml文件注册SpringMVC的前端控制器DispatcherServlet时使用url-pattern标签中使用/和/*的区别 /可以匹配.html或.js或.css等方式的请求路径,但不匹配*.jsp的请求路径/*可以匹配所有请求(包括.jsp请求), 例如在过滤器…

Kotlin空安全类型之平台类型

前言 众所周知,Kotlin的空安全很方便,能避免绝大部分的空安全问题 一般类型分为: 可空类型如 String? 不可空类型 String其中可空类型的String?可以赋值null或String类型的值,在使用时必须显式的进行空处理 而不可空类型的String,只能赋值String类型,无法向其赋值null,使用时…

JAVA基础-Stream流

引言 Java 8 版本新增的Stream,配合同版本出现的Lambda ,给我们操作集合(Collection)提供了极大的 便利。Stream流是JDK8新增的成员,允许以声明性方式处理数据集合,可以把Stream流看作是遍历数据集 合的一个…

【后端面经-Java】Java基本概念

【后端面经-Java】Java基本概念) 1. 面向对象和面向过程1.1 概念1.2 优缺点对比 2. C和Java的区别2.1 "去其糟粕"——Java同学,你对C的这些东西有什么意见?2.2 改进之处————Java同学,你的这个论文,&…

伦敦金投资仓位控制的方法

留意本栏目过去的文章的朋友都会发现,其实小编认为资金管理很重要,甚至重要性超过技术分析找到入场机会。在资金管理中,关于仓位的控制是一门很大的学问,在伦敦金投资中,仓位的控制关系到我们盈亏的多少,甚…

利用百度地图做个亚洲范围地震可视化特效果

地图叠加等值面效果,绘制掩体模型 地震闪动特效 地震热力图效果

【人工智能】局部搜索算法、爬山法、模拟退火、局部剪枝、遗传算法

文章目录 局部搜索算法内存限制局部搜索算法示例:n-皇后爬山算法随机重启爬山模拟退火算法局部剪枝搜索遗传算法小结局部搜索算法 在某些规模太大的问题状态空间内,A*往往不够用 问题空间太大了无法访问 f 小于最优的所有状态通常,甚至无法储存整个边缘队列解决方案 设计选择…

vue-cli脚手架创建创建的项目打包后无法正常打开报 Failed to load resource: net::ERR_FILE_NOT_FOUND错误

亲爱的小伙伴们,你们最近是否有遇到用使用最新的脚手架打包项目后index.html文件无法正常打开,然后控制台报错的情况呢,不要担心,这个坑今天被我踩到了并且被我解决了,下边就让我来给大家分享一下经验吧! …

树莓派4B通过wiringP库实现串口通信的实验

1.实现串口通信前的准备 树莓派4b实现与其它设备之间的串口通信需要做一些配置&#xff0c;可以点进这篇文章进行查看参考文章 wiringPi库串口相关的API参考文章链接wiringPI库串口API 2.实现单个字符的发送 #include <stdio.h> #include <wiringPi.h> #includ…

MFC第二十一天 CS架构多页面开发与数据交互、CImageList图像列表介绍 、CListCtrl-SetItem设置列表项的方法

文章目录 CImageList图像列表介绍CListCtrl图标的原理CListCtrl列表图标设置CListCtrl-SetItem设置列表项的方法 CS架构多页面开发与数据交互添加用户实现向导多页数据交互pch.hCLientXq.h CAppCPage1.hCPage1.cppCPage2.hCPage2.cppCWorkerDlg .hCWorkerDlg.cpp 多页数据修改C…

javascript实现九九乘法表

乘法表是初学者学习乘法基础的一个重要工具&#xff0c;同时也是程序员实践编程技能的一个常见项目。在本文中&#xff0c;我将介绍如何使用JavaScript实现一个简单的乘法表。 首先&#xff0c;我们需要明确乘法表的基本结构。乘法表通常是一个正方形的表格&#xff0c;包含从…

Ubuntu22.04部署K8s集群

Ubuntu22.04部署K8s集群 一、基础环境准备1.1 VMware Workstation Pro 17.01.2 Ubuntu22.04 二、系统环境配置2.1 设置Master与工作节点的机器名称及配置2.2 解析主机2.3 虚拟内存swap分区关闭2.4 开启IPv4转发2.5 设置时间同步2.6 开启防火墙的端口&#xff08;可选&#xff0…