Bean作用域和生命周期

小王学习录

  • 前言
  • Bean的作用域
    • 什么是Bean的作用域
    • Bean的六种作用域
      • 1. 单例作用域 singleton
      • 2. 原型作用域 prototype (多例作用域)
      • 3. 请求作用域 request
      • 4. 会话作用域 session
      • 5. 全局作用域 application
      • 6. Http WebSocket作用域 websocket
  • Spring的执行流程和Bean的生命周期
    • Spring的执行流程
    • Bean的生命周期
      • 1. 实例化Bean
      • 2. 设置属性
      • 3. Bean初始化
      • 4. 使用Bean
      • 5. 销毁Bean

前言

在之前的文章中我们知道, Spring是一个存放Bean的IoC容器, 这个容器的两大核心功能是存Bean和取Bean. 今天来详细了解一下Bean的作用域和生命周期.


Bean的作用域

什么是Bean的作用域

以前我们接触到的作用域说的是变量的可作用范围. 而今天要讲到Bean的作用域不同于之前的作用域, Bean的作用域说的是一个Bean在整个Spring框架中的行为模式. 行为模式有六种. 也就是作用域有六种. 下面将具体介绍这六种行为模式(作用域).

Bean的六种作用域

1. 单例作用域 singleton

singleton单例作用域, 顾名思义. 单例作用域就是在Spring框架中只存有该Bean的一个实例. 在整个框架中对该Bean的注入操作都是同一个对象.

这种作用域是Spring默认的Bean作用域, 适合于无状态的Bean. 所谓无状态就是该Bean的属性对象不需要更新.

当向Spring中存入一个Bean时, Spring默认这个Bean的作用域就是单例的, 因此不需要另外显式配置.

2. 原型作用域 prototype (多例作用域)

prototype多例作用域, 在每次获取Bean(ApplicationContext或通过注解进行注入)时, 都会获取到一个新的实例对象. 该实例对象遵循Spring框架对其进行的初始化操作(@Bean进行初始化).

实际上, 在每次获取实例对象时, 都是通过拷贝一份已有的原型对象实现的.

这种作用域适用于有状态的Bean. 需要注意的是, 这种作用域只适用于Spring框架, 对于Spring MVC和Spring Boot来说是不支持的.

当向Spring中存入一个Bean, 并且要将这个Bean的作用域设置为原型作用域时, 需要用到@Scope("prototype")或者@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
在这里插入图片描述

@Service
public class UserService {@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)@Beanpublic User setUser(){User user = new User();user.setUserid(2);user.setUsername("张三");user.setPassword("123");return user;}
}

3. 请求作用域 request

在每此http请求时会生成一个新的实例. 本此请求和响应公用一个实例. 适用于需要在同一次请求处理期间共享数据的Bean, 确保每个请求都有自己的实例. 在Spring MVC和Spring Boot中使用, Spring中不能使用.

使用时需要用到@RequestScope

4. 会话作用域 session

每个Http会话会创建一个实例, 该实例在整个会话中有效. 适用于在整个会话期间内共享数据的Bean. 在Spring MVC中使用, 在Spring中不能使用.

使用时需要用到@SessionScope注解.

5. 全局作用域 application

在整个web应用程序中共享一个Bean, 和单例模式相似但不同.

不同之处在于全局作用域是在整个web应用程序中共享一个Bean, 他是Spring Web中的作用域, 作用于Servlet容器.
而单例模式是在整个Spring容器中共享一个Bean. 是Spring中的作用域, 作用于IoC容器.

6. Http WebSocket作用域 websocket

在一个http webSocket的生命周期中定义一个Bean实例. 仅适用于Spring WebSocket中使用.

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

Spring的执行流程

Bean的执行流程是从启动Spring容器 ->初始化Bean -> 将Bean注册到Spring中 -> 将Bean装配到需要的类中.


public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Config.xml");UserController controller1 = context.getBean("userController", UserController.class);controller1.setUser();UserController2 controller2 = context.getBean("userController2", UserController2.class);controller2.print();}
}
  1. 启动Spring容器: 当代码执行到main方法中的ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Config.xml");时, 启动Spring容器. 加载指定的配置文件.
  2. 初始化Bean: 初始化Bean, 就是根据配置文件中指定的要扫描的路径进行扫描, 查找五大类注解和@Bean方法注解. 如果扫描到有需要存到Spring中的Bean, 先实例化(分配内存空间), 然后进行初始化.
  3. 注册Bean对象到容器中. 这就是往Spring中存Bean对象.
  4. 将Bean装配到需要的类中, 这就是注入Bean对象.

Bean的生命周期

生命周期是一个对象从诞生到销毁的整个生命过程, 这个过程就叫做一个对象的生命周期.

Bean的生命周期分为以下五步:

1. 实例化Bean

为Bean分配内存空间


2. 设置属性

将当前Bean所依赖的Bean注入进来. 为当前Bean的初始化做准备.


3. Bean初始化

  1. 发送通知: 继承一些通知接口, 如BeanNameAware, BeanFactoryAware, ApplicationContextAware. 实现这些接口的方法
public class Bean implements BeanNameAware, BeanFactoryAware {@Overridepublic void setBeanName(String s) {System.out.println("通知bean名为 -> " + s);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("通知工厂bean为 -> " + beanFactory);}
}
  1. 执行初始化的前置方法: 通过实现 BeanPostProcessor接口, 重写 postProcessBeforeInitialization方法. 前置方法和后置方法都不用显式调用

这个方法在Bean的初始化方法调用之前被调用. 实现BeanPostProcessor接口并覆写该方法, 可以在Bean初始化之前进行一些自定义的操作. 例如, 对Bean的属性进行修改或验证等.

public class Bean implements BeanNameAware, BeanFactoryAware , BeanPostProcessor {@Overridepublic void setBeanName(String s) {System.out.println("通知bean名为 -> " + s);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("通知工厂bean为 -> " + beanFactory);}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {System.out.println("执行初始化前置方法");return bean;}
}
  1. 执行初始化方法: 可以在xml文件中配置, 或者也可以通过注解@PostConstruct. 两者都出现时, 通过注解的方式优先级更高.
    (1) 通过xml文件: 在这里插入图片描述
    <bean id="bean" class="com.annotation.controller.Bean" init-method="beanInit"destroy-method="destory"> </bean>
    public void beanInit(){System.out.println("通过xml初始化bean");}

(2) 通过注解@PostConstruct:

    @PostConstructpublic void beanInit2(){System.out.println("通过注解初始化bean");}
  1. 执行初始化的后置方法

这个方法在Bean的初始化方法调用之后被调用. 和前置方法一样实现BeanPostProcessor接口, 重写后置方法postProcessAfterInitialization, 可以在Bean初始化之后进行一些自定义的操作. 例如, 对Bean进行额外的初始化或修改.

public class Bean implements BeanNameAware, BeanFactoryAware , BeanPostProcessor {@Overridepublic void setBeanName(String s) {System.out.println("通知bean名为 -> " + s);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("通知工厂bean为 -> " + beanFactory);}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {System.out.println("执行初始化前置方法");return bean;}public void beanInit(){System.out.println("通过xml初始化bean");}@PostConstructpublic void beanInit2(){System.out.println("通过注解初始化bean");}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {System.out.println("执行初始化后置方法");return bean;}
}

4. 使用Bean

    public void print(){System.out.println("使用bean");}

5. 销毁Bean

销毁Bean的方法与初始化Bean的方法类似, 可以在xml中配置, 也可以通过注解. 与初始化bean不同的是, bean的初始化方法无需显式调用, 而bean的销毁方法需要显式调用.
(1) 通过xml配置

    <bean id="bean" class="com.annotation.controller.Bean" init-method="beanInit"destroy-method="destory"> </bean>
    public void destory(){System.out.println("通过xml销毁bean");}

(2) 通过注解@PreDestroy

    @PreDestroypublic void destory2(){System.out.println("通过注解销毁bean");}

代码汇总:
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:context="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"><context:component-scan base-package="com.annotation"></context:component-scan><bean id="bean" class="com.annotation.controller.Bean" init-method="beanInit"destroy-method="destory" scope="prototype"> </bean>
</beans>

Bean类:

public class Bean implements BeanNameAware, BeanFactoryAware, BeanPostProcessor{@Overridepublic void setBeanName(String s) {System.out.println("通知bean名为 -> " + s);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("通知工厂bean为 -> " + beanFactory);}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {System.out.println("执行初始化前置方法");return bean;}public void beanInit(){System.out.println("通过xml初始化bean");}@PostConstructpublic void beanInit2(){System.out.println("通过注解初始化bean");}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {System.out.println("执行初始化后置方法");return bean;}public void destory(){System.out.println("通过xml销毁bean");}@PreDestroypublic void destory2(){System.out.println("通过注解销毁bean");}public void print(){System.out.println("使用bean");}
}

Main类:

public class Main {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Config.xml");
//        UserController controller1 = context.getBean("userController", UserController.class);
//        controller1.setUser();
//        UserController2 controller2 = context.getBean("userController2", UserController2.class);
//        controller2.print();Bean bean = context.getBean("bean", Bean.class);bean.print();bean.destory();bean.destory2();}
}

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

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

相关文章

网页设计--第6次课后作业

试用Vue相关指令完成对以下json数据的显示。显示效果如下&#xff1a; 其中&#xff1a;gender1 显示为女&#xff0c;gender2显示为男。价格超过30元&#xff0c;显示“有点小贵”。价格少于等于30元&#xff0c;则显示“价格亲民”。 data: {books: [{"id": "…

springboot集成字典注解

又是想下班的一天 文章目录 前言springboot使用AOP简单集成字典注解 一、通过注解进行字典赋值二、使用步骤1.添加注解2.序列化处理类3.实体类添加注解4.json返回值 总结 前言 springboot使用AOP简单集成字典注解 一、通过注解进行字典赋值 使用AOP切面实现字典的赋值,自动将…

MongoTemplate 常用查询

MongoTemplate是Spring Data MongoDB提供的一个Java编程接口&#xff0c;用于操作MongoDB数据库。它提供了一系列方法和功能&#xff0c;以便进行数据的插入、更新、删除和查询等操作。 使用MongoTemplate&#xff0c;你可以通过编写Java代码与MongoDB进行交互&#xff0c;而无…

二百一十四、Linux——Linux系统时间比电脑时间慢5分钟

一、目的 服务器重启后&#xff0c;发现Linux的系统时间比电脑时间慢5分钟&#xff0c;于是看了些博客&#xff0c;终于找到了解决方法&#xff0c;记录一下&#xff0c;以防止后面出现同样的问题 二、问题 通过date查看&#xff0c;Linux系统时间比电脑时间慢5分钟 &#…

IEEE RAS 机器人最优控制(Model-based Optimization for Robotics)学习资料

系列文章目录 前言 电气和电子工程师学会机器人模型优化技术委员会 一、学习资料 1.1 教程和暑期学校 2020 年 Memmo 欧盟项目暑期班2019年Memmo欧盟项目冬季学校Matthias Gerdts&#xff08;德国慕尼黑联邦国防军大学&#xff09;在拜罗伊特 OMPC 2013 上举办的最优控制教程…

详解vue生命周期

vue2 生命周期 Vue.js是一个流行的JavaScript框架&#xff0c;它使用了一套生命周期钩子函数来管理组件的创建、更新和销毁过程。以下是Vue组件的生命周期钩子函数&#xff1a; beforeCreate&#xff1a;在实例初始化之后&#xff0c;数据观测 (data observer) 和 event/watch…

字节跳动ZNS SSD应用案例解析

一、ZNS SSD基本原理 ZNS SSD的原理是把namespace空间划分多个zone空间&#xff0c;zone空间内部执行顺序写。这样做的优势&#xff1a; 降低SSD内部的写放大&#xff0c;提升SSD的寿命 降低OP空间&#xff0c;host可以获得更大的使用空间 降低SSD内部DRAM的容量&#xff0c;…

一款可无限扩展的软件定时器开源框架项目代码

摘自链接 时间片轮询架构如何稳定高效实现&#xff0c;取代传统的标志位判断方式&#xff0c;更优雅更方便地管理程序的时间触发操作。 可以在STM32单片机上运行。

基于SSM的社区管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

LeetCode(52)最小栈【栈】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 最小栈 1.题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void…

区分工业设计软件中CAD、CAE、CAM、PDM等概念

工业设计软件是专门用于辅助工业设计师在产品设计和开发过程中进行各种任务的计算机程序。这些软件提供了广泛的工具和功能&#xff0c;帮助设计师创建、分析、修改和可视化产品的概念和详细设计。 CAD 计算机辅助设计&#xff08;Computer-Aided Design&#xff0c;CAD&…

15、SQL注入——Sqlmap

文章目录 一、Sqlmap简介1.1 sqlmap可以对URL干嘛&#xff1f;1.2 Sqlmap支持的注入技术1.3 SQLmap检测注入漏洞的流程1.4 Sqlmap的误报检测机制 二、sqlmap基本使用 一、Sqlmap简介 sqlmap使用教程 1.1 sqlmap可以对URL干嘛&#xff1f; 判断可注入的参数判断可以使用哪一种…

汽车电子智能保险丝解决方案

一、背景知识 在过去的几十年里&#xff0c;电子在汽车系统创新中发挥了关键作用。新型半导体器件具有新颖的功能&#xff0c;增强了车辆机械系统提供的功能。 虽然半导体解决方案和电子产品将继续在汽车电子产品中发挥关键作用&#xff0c;但展望未来&#xff0c;汽车创新将…

css顺时针旋转90°再3D中绕Y轴旋转180°

CSS 顺时针旋转 90 再 3D 中绕 Y 轴旋转 180 的示例代码如下&#xff1a; div {transform: rotate(90deg) perspective(500px) rotateY(180deg); }在这个示例中&#xff0c;元素被先进行了 2D 顺时针旋转 90&#xff0c;然后设置了 perspective 属性来定义元素的视角距离&…

UE4 材质实现Glitch效果

材质实现Glitch效果 UE4 材质实现Glitch效果预览1预览2 UE4 材质实现Glitch效果 预览1 添加材质函数&#xff1a; MF_RandomNoise 添加材质&#xff1a; 预览2 添加材质函数MF_CustomPanner&#xff1a; 添加材质函数&#xff1a;MF_Glitch 材质添加&#xff1a; 下面用…

Docker 部署 2FAuth 服务

拉取最新版本的 2FAuth 镜像&#xff1a; $ sudo docker pull 2fauth/2fauth:latest在本地预先创建好 2fauth 目录, 用于映射 2FAuth 容器内的 /2fauth 目录。 使用以下命令, 在 前台 运行 2FAuth 容器: $ sudo docker run -it --rm --name 2fauth -p 10085:8000/tcp -v /ho…

3D材质编辑:制作被火烧的木头

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时&#xff0c;有几种不同的风格&#xf…

css实现头部占一定高度,内容区占剩余高度可滚动

上下布局&#xff1a; <div class"container"><header class"header">头部内容</header><div class"content">内容区域</div> </div>.container {display: flex;flex-direction: column;height: 100vh; /*…

SQL Server 2017数据库window server服务器改名操作

在window服务器修改机器名重新加域后&#xff0c;需要执行下面的SQL语句修改数据库里面记录的机器名字&#xff0c;才能在修改后通过新名字连接数据库。 if serverproperty(servername) <> servername begin declare server sysname set server ser…

53. Protocol buffer 的Go使用

文章目录 一、介绍二、安装三、protoc3语法1、 protoc3 与 protoc2区别2、proto3生成go代码包Message内嵌Message字段单一标量字段单一message字段可重复字段slicemap字段枚举 一、介绍 Protobuf是Google旗下的一款平台无关&#xff0c;语言无关&#xff0c;可扩展的序列化结构…