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

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;}@Overridepublic 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 {@Autowiredprivate 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 {@Autowiredprivate 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 {@Overridepublic void setBeanName(String s) {System.out.println("执行了 BeanNameAware -> " + s);}@PostConstructpublic void doPostConstruct() {System.out.println("执行了 @PostConstruct");}public void myinit() {System.out.println("执行了 myinit");}@PreDestroypublic 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 {@Autowiredprivate User user;@Overridepublic void setBeanName(String s) {System.out.println("执行了 BeanNameAware -> " + s);}@PostConstructpublic void doPostConstruct() {System.out.println("执行了 @PostConstruct");System.out.println(user.toString());}public void myinit() {System.out.println("执行了 myinit");}@PreDestroypublic 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.mzph.cn/news/179237.shtml

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

相关文章

colab notebook导出为PDF

目录 方法一&#xff1a;使用浏览器打印功能 方法二&#xff1a;使用nbconvert转换 方法三&#xff1a;在线转换 方法一&#xff1a;使用浏览器打印功能 一般快捷键是CTRLP 然后改变目标打印机为另存为PDF 这样就可以将notebook保存为PDF了 方法二&#xff1a;使用nbconver…

芯片技术前沿:了解构现代集成电路的设计与制造

芯片技术前沿&#xff1a;解构现代集成电路的设计与制造 摘要&#xff1a;本文将深入探讨芯片技术的最新进展&#xff0c;重点关注集成电路的设计与制造。我们将带领读者了解芯片设计的基本流程&#xff0c;包括电路分析、版图设计和验证等步骤&#xff0c;并介绍当前主流的制…

强化学习中的深度Q网络

深度 Q 网络&#xff08;Deep Q-Network&#xff0c;DQN&#xff09;是一种结合了深度学习和强化学习的方法&#xff0c;用于解决离散状态和离散动作空间的强化学习问题。DQN 的核心思想是使用深度神经网络来近似 Q 函数&#xff0c;从而学习复杂环境中的最优策略。 以下是 DQN…

从苹果到蔚来,「车手互联」网罗顶级玩家

作者 |Amy 编辑 |德新 汽车作为家之外的第二大移动空间&#xff0c;正与手机这一移动智能终端进行「车手互联」。 车手互联始于十年前的苹果CarPlay&#xff0c;一度成为时代弄潮儿&#xff0c;不断有后继者模仿并超越。时至今日&#xff0c;CarPlay2.0依旧停留在概念阶段&am…

RK3568笔记六:基于Yolov8的训练及部署

若该文为原创文章&#xff0c;转载请注明原文出处。 基于Yolov8的训练及部署&#xff0c;参考鲁班猫的手册训练自己的数据集部署到RK3568,用的是正点的板子。 1、 使用 conda 创建虚拟环境 conda create -n yolov8 python3.8 ​ conda activate yolov8 2、 安装 pytorch 等…

osgFX扩展库-异性光照、贴图、卡通特效(1)

本章将简单介绍 osgFX扩展库及osgSim 扩展库。osgFX库用得比较多,osgSim库不常用&#xff0c;因此&#xff0c;这里只对这个库作简单的说明。 osgFX扩展库 osgFX是一个OpenSceneGraph 的附加库&#xff0c;是一个用于实现一致、完备、可重用的特殊效果的构架工具&#xff0c;其…

UE 事件分发机制 day9

观察者模式原理 观察者模式通常有观察者与被观察者&#xff0c;当被观察者状态发生改变时&#xff0c;它会通知所有的被观察者对象&#xff0c;使他们能够及时做出响应&#xff0c;所以也被称作“发布-订阅模式”。总得来说就是你关注了一个主播&#xff0c;主播的状态改变会通…

Fabric:搭建自定义网络

Hyperledger Fabric: V2.5.4 写在最前 从本篇博客开始&#xff0c;将陆续介绍使用Fabric搭建自定义网络及部署执行链码的过程。本篇主要介绍如何搭建网络。   由于前文在安装Fabric的时候&#xff0c;已经将目录fabric-samples/bin加入到了环境变量PATH中&#xff0c;所以正文…

数据结构 / day01 作业

1.定义结构体数组存储5个学生的信息&#xff1a;姓名&#xff0c;年龄&#xff0c;性别 定义函数实现输入&#xff0c;要求形参使用结构体指针接收 函数实现5个学生年龄排序(注意对年龄排序时&#xff0c;交换的是所有信息) 定义函数实现输出&#xff0c;要求形参使用结构体…

(5h)Unity3D快速入门之Roll-A-Ball游戏开发

DAY1&#xff1a;Unity3D安装 链接 DAY2&#xff1a;构建场景&#xff0c;编写代码 链接 内容&#xff1a;WASD前后左右移动、摄像机跟随 DAY3&#xff1a;待更新 DAY4&#xff1a;待更新 DAY5&#xff1a;待更新

jekins CVE-2018-1000861 漏洞复现

jekins CVE-2018-1000861 漏洞复现 ‍ 名称: jenkins 命令执行 &#xff08;CVE-2018-1000861&#xff09; 描述: ​Jenkins 可以通过其网页界面轻松设置和配置,其中包括即时错误检查和内置帮助。 插件 通过更新中心中的 1000 多个插件,Jenkins 集成了持续集成和持续交付工具…

INFINI Gateway 与华为鲲鹏完成产品兼容互认证

何为华为鲲鹏认证 华为鲲鹏认证是华为云围绕鲲鹏云服务&#xff08;含公有云、私有云、混合云、桌面云&#xff09;推出的一项合作伙伴计划&#xff0c;旨在为构建持续发展、合作共赢的鲲鹏生态圈&#xff0c;通过整合华为的技术、品牌资源&#xff0c;与合作伙伴共享商机和利…

AI大模型相关产品的数据飞轮如何建设?

1、背景 数据飞轮&#xff0c;是今年大模型带火的一个典型词汇&#xff0c;通过客户在应用程序中输入的提示词这样的数据反馈&#xff0c;使大模型快速迭代。简单说&#xff1a;好的产品 -> 更多的用户数据 -> 更好的模型质量 -> 更好的产品就进入了一个正向循环。一…

【Apifox】测试工具自动编写接口文档

在开发过程中&#xff0c;我们总是避免不了进行接口的测试&#xff0c; 而相比手动敲测试代码&#xff0c;使用测试工具进行测试更为便捷&#xff0c;高效 今天发现了一个非常好用的接口测试工具Apifox 相比于Postman&#xff0c;他还拥有一个非常nb的功能&#xff0c; 在接…

小白备战蓝桥杯:Java基础语法

一、注释 IDEA注释快捷键&#xff1a;Ctrl / 单行注释&#xff1a; //注释信息 多行注释&#xff1a; /* 注释信息 */ 二、字面量 常用数据&#xff1a;整数、小数、字符串&#xff08;双引号&#xff09;、字符&#xff08;单引号&#xff09;、布尔值&#xff08;tr…

JavaScript 的 DOM 知识点有哪些?

文档对象模型&#xff08;Document Object Model&#xff0c;简称 DOM&#xff09;&#xff0c;是一种与平台和语言无关的模型&#xff0c;用来表示 HTML 或 XML 文档。文档对象模型中定义了文档的逻辑结构&#xff0c;以及程序访问和操作文档的方式。 当网页加载时&#xff0…

unity3d 旋转cube时变形

将cube移到父路径同级&#xff0c;重置再&#xff0c;更改角度&#xff0c;或者将父路径先重置&#xff0c;再将cube移动到父节点下面

Corel产品注册机Corel Products KeyGen 2023 – XFORCE解决会声会影2023试用30天

CorelDRAW注册机2023支持全系列产品_Corel Products KeyGen 2023 X-FORCE v8 CorelDRAW注册机2023支持全系列产品_Corel Products KeyGen 2023 X-FORCE v8&#xff0c;Corel产品注册机&#xff08;Corel Products KeyGen 2023 – XFORCE&#xff09;&#xff0c;支持Corel旗下所…

Django请求生命周期流程

浏览器发起请求。 先经过网关接口&#xff0c;Django自带的是wsgiref&#xff0c;请求来的时候解析封装&#xff0c;响应走的时候打包处理&#xff0c;这个wsgiref模块本身能够支持的并发量很少&#xff0c;最多1000左右&#xff0c;上线之后会换成uwsgi&#xff0c;并且还会加…

人工智能技术发展漫谈

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 人工智能发展历程 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;的发展历史可以追溯到20世纪中叶。以下是一些关键时刻和阶段&#xff1a; 起…