JavaEE进阶学习:Bean 作用域和生命周期

news2024/11/17 7:38:38

1.Bean 作用域

.通过一个案例来看 Bean 作用域的问题

假设现在有一个公共的 Bean,提供给 A 用户和 B 用户使用,然而在使用的途中 A 用户却“悄悄”地修改了公共 Bean 的数据,导致 B 用户在使用时发生了预期之外的逻辑错误。

我们预期的结果是,公共 Bean 可以在各自的类中被修改,但不能影响到其他类。

package com.java.demo.model;

/**
 * @projectName: Demo
 * @package: com.java.demo.model
 * @className: User
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:18
 * @version: 1.0
 */
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 + '\'' +
                '}';
    }
}

package com.java.demo.model;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * @projectName: Demo
 * @package: com.java.demo.model
 * @className: Users
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:18
 * @version: 1.0
 */

/**
 * 公共类
 */
@Component
public class Users {

    /**
     * 公共对象
     * @return
     */
    @Bean("user")
    public User getUser() {
        User user = new User();
        user.setId(1);
        user.setName("凹凸曼");
        return user;
    }
}

package com.java.demo.controller;

/**
 * @projectName: Demo
 * @package: com.java.demo.controller
 * @className: UserController
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/26 21:36
 * @version: 1.0
 */

import com.java.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * 用户控制器 - 版本
 * 作者:李四
 */
@Controller
public class UserController {
    @Autowired
    private User user;

    public void doMethod() {

        System.out.println("UserController user -> " + user);
    }
}

package com.java.demo.controller;

/**
 * @projectName: Demo
 * @package: com.java.demo.controller
 * @className: UserController2
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:23
 * @version: 1.0
 */

import com.java.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * 用户控制器 - 版本2
 * 作者:张三
 */
@Controller
public class UserController2 {

    @Autowired
    private User user;

    public void doMethod() {
        User user2 = user;
        System.out.println("UserController2 修改之前: user -> " + user);
        user2.setName("三三");
        System.out.println("UserController2 修改之后: user -> " + user);
    }
}

import com.java.demo.controller.UserController;
import com.java.demo.controller.UserController2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @projectName: Demo
 * @package: com.java.demo
 * @className: App
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:31
 * @version: 1.0
 */
public class App {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        UserController2 userController2 = context.getBean("userController2",UserController2.class);
        userController2.doMethod();

        UserController userController = context.getBean("userController",UserController.class);
        userController.doMethod();
    }
}

在这里插入图片描述

在这里插入图片描述
我们的Users 默认是单例模式,想要 公共 Bean 可以在各自的类中被修改,但不能影响到其他类

我们可以加一个作用域

在这里插入图片描述

1.什么叫作用域

Bean 作用域指的是 Bean 在 Spring 容器中的某种行为(单例,原型…)

2.Bean 的 6 种作用域

Spring 容器在初始化⼀个 Bean 的实例时,同时会指定该实例的作用域。Spring有 6 种作用域,最后四种是基于 Spring MVC 生效的:

  1. singleton:单例作用域
  2. prototype:原型作用域(多例作用域)
  3. request:请求作用域 (只适用于Spring MVC 项目)
  4. session:回话作用域 (一个 HTTP 会话共享一个Bean,只适用于Spring MVC 项目)
  5. application:全局作用域(表示的是一个 Context 容器共享一个作用域,只适用于Spring MVC 项目)
  6. websocket:HTTP WebSocket 作用域

单例模式的 Bean 是线程安全的么?

不是,使用TreadLocal(本地线程变量)

3.设置 Bean 的作用域

1.@Scope(“prototype”)

package com.java.demo.model;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @projectName: Demo
 * @package: com.java.demo.model
 * @className: Users
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:18
 * @version: 1.0
 */

/**
 * 公共类
 */
@Component
public class Users {

    /**
     * 公共对象 -> 默认是单例模式
     * @return
     */
    @Bean(name = "user")
    @Scope("prototype") //原型模式 | 多例模式(每一次使用注解请求的时候,都会 new 一个新的之前对象)
    //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User getUser() {
        User user = new User();
        user.setId(1);
        user.setName("凹凸曼");
        return user;
    }
}

2.@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

package com.java.demo.model;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @projectName: Demo
 * @package: com.java.demo.model
 * @className: Users
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 16:18
 * @version: 1.0
 */

/**
 * 公共类
 */
@Component
public class Users {

    /**
     * 公共对象 -> 默认是单例模式
     * @return
     */
    @Bean(name = "user")
    //@Scope("prototype") //原型模式 | 多例模式(每一次使用注解请求的时候,都会 new 一个新的之前对象)
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User getUser() {
        User user = new User();
        user.setId(1);
        user.setName("凹凸曼");
        return user;
    }
}

2.Spring 执行流程和 Bean 的生命周期

1.执行流程

在这里插入图片描述

Bean 执行流程(Spring 执行流程):启动 Spring 容器 -> 实例化 Bean(分配内存空间,从无到有) -> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的类中(取操作)。

2.Bean 的生命周期

所谓的生命周期指的是⼀个对象从诞生到销毁的整个生命过程,我们把这个过程就叫做⼀个对象的生命周期。

  1. 实例化(内存分配空间)

  2. 设置 Bean 的属性(进行依赖注入,将依赖的 Bean 赋值到当前类的属性上)

  3. Bean 的初始化

  • 执行各种通知
  • 初始化的前置方法
  • 初始化方法
  • 初始化的后置方法
  1. 使用 Bean

  2. 销毁 Bean

实例化和属性设置是 Java 级别的系统“事件”,其操作过程不可人工干预和修改;而初始化是给开发者提供的,可以在实例化之后,类加载完成之前进行自定义“事件”处理。
在这里插入图片描述

import org.springframework.beans.factory.BeanNameAware;

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

/**
 * @projectName: untitled
 * @package: PACKAGE_NAME
 * @className: BeanLifeComponent
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 21:12
 * @version: 1.0
 */
public class BeanLifeComponent implements BeanNameAware {
    @Override
    public void setBeanName(String s) {
        System.out.println("执行了 BeanNameAware -> " + s);
    }
    @PostConstruct
    public void doPostConstruct() {
        System.out.println("执行了 @PostConstruct");
    }
    public void myinit() {
        System.out.println("执行了 myinit");
    }

    @PreDestroy
    public void doPreDestroy() {
        System.out.println("执行了 @PreDestroy");

    }

    public void useBean() {
        System.out.println("使用 Bean");
    }

}

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @projectName: untitled
 * @package: PACKAGE_NAME
 * @className: BeanLifeTest
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 21:25
 * @version: 1.0
 */
public class BeanLifeTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        BeanLifeComponent component =
                context.getBean("mybean",BeanLifeComponent.class);
        component.useBean();
        context.close();
    }
}

<?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">
    <content:component-scan base-package="com.java.demo"></content:component-scan>
    <bean id="mybean" class="BeanLifeComponent" init-method="myinit" ></bean>
</beans>

在这里插入图片描述

在这里插入图片描述
符合上述 Bean初始化 的流程

3.为什么要先设置属性在进行初始化

import com.java.demo.model.User;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;

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

/**
 * @projectName: untitled
 * @package: PACKAGE_NAME
 * @className: BeanLifeComponent
 * @author: 王嘉辉
 * @description:
 * @date: 2023/11/28 21:12
 * @version: 1.0
 */
public class BeanLifeComponent implements BeanNameAware {

    @Autowired
    private User user;

    @Override
    public void setBeanName(String s) {
        System.out.println("执行了 BeanNameAware -> " + s);
    }

    @PostConstruct
    public void doPostConstruct() {
        System.out.println("执行了 @PostConstruct");
        System.out.println(user.toString());
    }

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

    @PreDestroy
    public void doPreDestroy() {
        System.out.println("执行了 @PreDestroy");

    }

    public void useBean() {
        System.out.println("使用 Bean");
    }

}

在这里插入图片描述

在 Bean 的生命周期中,先设置属性再进行初始化的原因是因为在实例化 Bean 对象时,Spring 容器会调用 Bean 的构造方法创建 Bean 对象,并将对象的属性注入到 Bean 中。如果在初始化之前就进行依赖注入,那么被注入的属性可能还没有完全初始化,这样可能会导致对象状态不一致的问题。

当初始化 Bean 时,容器会调用 Bean 的初始化方法。这个时候,Bean 对象已经被完全初始化,可以安全地进行一些初始化操作。因此,先设置属性再进行初始化可以确保 Bean 对象的完整性和正确性。

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

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

相关文章

如何修改.exe文件的修改时间,亲测有效

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 演示视频&#xff1a; 10秒钟实现将文件的修改…

Achronix推出基于FPGA的加速自动语音识别解决方案

提供超低延迟和极低错误率&#xff08;WER&#xff09;的实时流式语音转文本解决方案&#xff0c;可同时运行超过1000个并发语音流 2023年11月——高性能FPGA芯片和嵌入式FPGA&#xff08;eFPGA IP&#xff09;领域的领先企业Achronix半导体公司日前自豪地宣布&#xff1a;正式…

曲面拼接oled屏幕为何受到企业展览青睐

曲面拼接OLED屏幕受到企业展览青睐的原因主要有以下几点&#xff1a; 创新的技术&#xff1a;曲面拼接OLED屏幕采用先进的OLED技术&#xff0c;具有自发光原理&#xff0c;可以实现真正的黑色和高对比度&#xff0c;呈现出生动的图像。其每个像素都能独立发光&#xff0c;没有背…

世微 低功耗 PFM DC-DC 升压芯片 AP8105 干电池手持设备驱动IC

概述 AP8105 系列产品是一种高效率、低纹波、工作频率高的 PFM 升压 DC-DC 变换器。AP8105 系列产品仅需要四个外围元器件&#xff0c;就可完成将低输入的电池电压变换升压到所需的工作电压&#xff0c;非常适合于便携式 1&#xff5e;4 节普通电池应用的场合。电路采用了高性能…

python实现获取aws route53域名信息

最近由于工作原因接触到aws的服务&#xff0c;我需要实时获取所有的域名信息&#xff0c;用于对其进行扫描&#xff0c;因此写了一个自动化爬取脚本 给需要的人分享。 1.基础准备 代码环境&#xff1a;python3 第三方库&#xff1a;boto3 &#xff08;安装方法pip install…

springboot+netty化身Udp服务端,go化身客户端模拟设备实现指令联动

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 springbootnetty化身Udp服务端&#xff0c;go化身客户端模拟设备实现指令联动 &#x1f517;涉及链接前言异步通信的优势异步通信的优势&#xff1a;异步通信的应用场景&…

腾讯云双11活动最后一天,错过再等一年!

腾讯云双11活动已经进入尾声&#xff0c;距离活动结束仅剩最后一天&#xff0c;记得抓住这次上云好时机&#xff0c;错过这次&#xff0c;就要等到下一年才能享受到这样的优惠力度了&#xff01; 活动地址&#xff1a; 点此直达腾讯云双11活动主会场 活动详情&#xff1a; 1…

Retrofit中的注解

一、Retrofit中的注解有那些&#xff1f; 方法注解&#xff1a;GET ,POST,PUT,DELETE,PATH,HEAD,OPTIONS,HTTP标记注解&#xff1a;FormUrlEncoded&#xff0c;Multpart&#xff0c;Streaming参数注解&#xff1a;Query&#xff0c;QueryMap&#xff0c;Body&#xff0c;Field…

vue+el-tooltip 封装提示框组件,只有溢出才提示

效果 封装思路 通过控制el-tooltip的disabled属性控制是否提示通过在内容上绑定mouseenter事件监听内容宽度和可视宽度&#xff0c;判断内容是否溢出 封装代码 <template><div style"display: flex" class"column-overflow"><el-tooltip…

XUbuntu22.04之OBS强大录屏工具(一百九十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【Linux】ln命令使用

ln命令 ln是linux中又一个非常重要命令&#xff0c;请大家一定要熟悉。它的功能是为某一个文件在另外一个位置建立一个同步的链接&#xff0c;这个命令最常用的参数是-s&#xff0c;具体用法是&#xff1a;ln –s 源文件 目标文件。 当我们需要在不同的目录&#xff0c;用到相…

第三方检测机构实验室信息管理系统LIMS全套源码

​LIMS实验室信息管理系统源码&#xff0c;支持二次开发 LIMS实验室信息管理系统是一种软件类型&#xff0c;旨在通过跟踪与样品、实验、实验室工作流程和仪器相关的数据&#xff0c;提高实验室产能和效率。覆盖实验室从合同审批、委托下单、样品管理、生产调度、检测记录、报告…

Talk | UCSB博士生许闻达:细粒度可解释评估初探

本期为TechBeat人工智能社区第551期线上Talk。 北京时间11月29日(周三)20:00&#xff0c;UC Santa Barbara博士生—许闻达的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “细粒度可解释评估初探”&#xff0c;分享了他们团队在具备解释性的细粒度…

彻底删除VsCode配置和安装过的插件与缓存

前言 当你准备对 Visual Studio Code&#xff08;VSCode&#xff09;进行重新安装时&#xff0c;可能遇到一个常见问题&#xff1a;重新安装后&#xff0c;新的安装似乎仍然保留了旧的配置信息&#xff0c;这可能会导致一些麻烦。这种情况通常是由于卸载不彻底所致&#xff0c…

MySQL官网推荐书籍

MySQL官网推荐书籍 图片有防盗链csdn转存失败。有图版传送门MySQL官网推荐书籍 高效的MySQL性能&#xff1a;Daniel Nichter的最佳实践和技术 Daniel Nichter 向您展示了如何应用直接影响 MySQL 性能的最佳实践和技术。您将学习如何通过分析查询执行、为常见 SQL 子句和表联接…

一套后台管理系统的入门级的增删改查(vue3组合式api+elemment-plus)

一、页面示意&#xff1a; 图一 图二 二、组件结构 列表组件 &#xff1a;index.vue,对应图一添加组件&#xff1a;add.vue&#xff0c;对应图二&#xff0c;用抽屉效果编辑组件&#xff1a;edit.vue&#xff0c;和添加组件的效果一个。 三、代码 1、列表组件: index.vue …

Ubuntu使用Nginx部署前端项目——记录

安装nginx 依次执行以下两条命令进行安装&#xff1a; sudo apt-get update sudo apt-get install nginx通过查看版本号查看是否安装成功&#xff1a; nginx -v补充卸载操作&#xff1a; sudo apt-get remove nginx nginx-common sudo apt-get purge nginx nginx-common su…

为计算机设计一个完美的思维模型,帮找bug和漏洞,一起来做渗透测试吧 最赚钱的10种思维模型

芒格 如果我不能淘汰自己一年前的思维模型&#xff0c;这一年我就白过了。&#xff08;终身学习&#xff0c;不断迭代自己。&#xff09; 思维模型是什么&#xff0c;有哪些&#xff1f; 思维模型是用来简化和理解复杂现实世界的概念框架。它们是一种思考和解决问题的工具&a…

8个最流行的Revit插件【2023-2024】

NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 Revit 已取代 AutoCAD 成为全球行业标准软件。 随着设计复杂性的增加&#xff0c;近年来插件变得更加必要。 热…

【腾讯地图】【微信小程序】地图选点

【相关文章】 【腾讯地图】【微信小程序】地图选点 【腾讯地图】【微信小程序】路线规划 【腾讯地图】【微信小程序】城市记录&#xff08;基于地图选点入门版&#xff09; 【效果展示】 【官方文档】 微信小程序插件-地图选点插件 【完善流程】 当前操作和官方文档操作有部…