Spring Scope

news2024/12/23 18:48:38

Spring中五种 Scope域

  • singleton,容器启动时创建(未设置延迟),容器关闭时销毁【单例】
  • prototype,每次使用时创建,不会自动销毁,需要调用 DefaultListableBeanFactory.destroyBean(bean) 销毁【原型】
  • request,每次请求用到此 bean 时创建,请求结束时销毁(每次请求来都会创建一个request域对象放到web request域当中,请求结束会被销毁)
  • session,每个会话用到此 bean 时创建,会话结束时销毁(会话创建时会把session对象创建出来放入web session中,会话结束时销毁,会话有默认销毁时间可以设置,长时间不访问自动销毁)
  • application,web 容器用到此 bean 时创建,容器停止时销毁(ServletContext创建后,首次用bean将其放入ServletContext中,销毁Spring未实现)

单例Bean注入其他Scope Bean不做处理,会出现Scope生效的情况,需要在注入bean对象上添加@Lazy注解

演示:

不同scope域的bean

@Scope("application")
@Component
public class BeanForApplication {
    private static final Logger log = LoggerFactory.getLogger(BeanForApplication.class);

    @PreDestroy
    public void destroy() {
        log.debug("destroy");
    }
}

@Scope("session")
@Component
public class BeanForSession {
    private static final Logger log = LoggerFactory.getLogger(BeanForSession.class);

    @PreDestroy
    public void destroy() {
        log.debug("destroy");
    }
}

@Scope("request")
@Component
public class BeanForRequest {
    private static final Logger log = LoggerFactory.getLogger(BeanForRequest.class);

    @PreDestroy
    public void destroy() {
        log.debug("destroy");
    }

}
@RestController
public class MyController {
    
    @Lazy
    @Autowired
    private BeanForRequest beanForRequest;

    @Lazy
    @Autowired
    private BeanForSession beanForSession;

    @Lazy
    @Autowired
    private BeanForApplication beanForApplication;

    @GetMapping(value = "/test", produces = "text/html")
    public String test(HttpServletRequest request, HttpSession session) {
        ServletContext sc = request.getServletContext();
        String sb = "<ul>" +
                    "<li>" + "request scope:" + beanForRequest + "</li>" +
                    "<li>" + "session scope:" + beanForSession + "</li>" +
                    "<li>" + "application scope:" + beanForApplication + "</li>" +
                    "</ul>";
        return sb;
    }
}

分析 - singleton 注入其它 scope 失效

以单例注入多例为例

有一个单例对象 E

@Component
public class E {
    @Autowired
    private F1 f1;

    public F1 getF1() {
        return f1;
    }
}

要注入的对象 F1 期望是多例

@Component
@Scope("prototype")
public class F1 {
    private static final Logger log = LoggerFactory.getLogger(F.class);

    public F1() {
        log.info("F1()");
    }
}

测试:

   E e = context.getBean(E.class);
   log.debug("{}", e.getF1());
   log.debug("{}", e.getF1());

输出:

com.lkl.spring.chapter8.sub.F1@72d1ad2e
com.lkl.spring.chapter8.sub.F1@72d1ad2e

发现它们是同一个对象,而不是期望的多例对象

对于单例对象来讲,依赖注入仅发生了一次,后续再没有用到多例的 F1,因此 E 用的始终是第一次依赖注入的 F

e 创建
e set 注入 f
f 创建

解决

  • 仍然使用 @Lazy 生成代理
  • 代理对象虽然还是同一个,但当每次使用代理对象的任意方法时,由代理创建新的 f 对象
使用f方法
使用f方法
使用f方法
e 创建
e set 注入 f代理
f 创建
f 创建
f 创建
@Component
public class E {

    @Autowired
    @Lazy
    public void setF(F f) {
        this.f = f;
        log.info("setF(F f) {}", f.getClass());
    }

    // ...
}

注意

  • @Lazy 也可以加在成员变量上,但加在 set 方法上的目的是可以观察输出,加在成员变量上就不行了
  • @Autowired 加在 set 方法的目的类似
        E e = context.getBean(E.class);
        log.debug("{}", e.getF1().getClass());
        log.debug("{}", e.getF1());
        log.debug("{}", e.getF1());

输出:

class com.lkl.spring.chapter8.sub.F1$$EnhancerBySpringCGLIB$$278636ac
com.lkl.spring.chapter8.sub.F1@9597028
com.lkl.spring.chapter8.sub.F1@4efbca5a

f 对象的类型是代理类型

解决方法

  1. 单例注入其它 scope 的四种解决方法

    • @Lazy
    • @Scope(value = “prototype”, proxyMode = ScopedProxyMode.TARGET_CLASS)

    image-20230713220952991

    • ObjectFactory
    • ApplicationContext
  2. 解决方法虽然不同,但理念上殊途同归: 都是推迟其它 scope bean 的获取

@Component
public class E {

    // 方法一
    @Lazy
    @Autowired
    private F1 f1;

    // 方法二
    @Autowired
    private F2 f2;

    // 方法三
    @Autowired
    private ObjectFactory<F3> f3;

    // 方法四
    @Autowired
    private ApplicationContext context;

    public F1 getF1() {
        return f1;
    }

    public F2 getF2() {
        return f2;
    }

    public F3 getF3() {
        return f3.getObject();
    }

    public F4 getF4() {
        return context.getBean(F4.class);
    }
}

前两个使用代理对象解决

第三种通过对象工厂,通过对象工厂获取对象,工厂可以识别对象多例类型

最后一种,直接通过ApplicationContext容器获取多例对象

使用代理对象会有点性能损耗,后面两种方法会好些

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

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

相关文章

前端Web实战:从零打造一个类Visio的流程图拓扑图绘图工具

前言 大家好&#xff0c;本系列从Web前端实战的角度&#xff0c;给大家分享介绍如何从零打造一个自己专属的绘图工具&#xff0c;实现流程图、拓扑图、脑图等类Visio的绘图工具。 你将收获 免费好用、专属自己的绘图工具前端项目实战学习如何从0搭建一个前端项目等基础框架项…

小白到运维工程师自学之路 第五十三集 (rsync+inotify备份)

一、概述 Rsync是一个用于在不同计算机之间同步文件和文件夹的工具。它可以在本地计算机和远程服务器之间复制、更新和备份文件。rsync通过比较源和目标文件的差异来最小化传输的数据量&#xff0c;从而提供高效的文件同步功能。 Inotify是Linux内核提供的一种机制&#xff0…

【C++】模板(函数模板与类模板)讲解

本篇文章会对C中的模板进行讲解&#xff0c;其中会对函数模板和类模板进行讲解。希望本篇文章会对你有所帮助。 文章目录 一、函数模板 1、1 模板的引入 1、2 函数模板举例讲解 1、2、1 函数模板的概念 1、2、2 函数模板格式 1、2、3 函数模板实例化 1、2、4 模板参数的匹配原则…

2023下半年软考高级系统架构设计师怎么报名?

软考高级系统架构设计师报名时间&#xff1a; 广西2023下半年软考高级系统架构设计师报名时间&#xff1a;8月15日8:00至8月24日17:00 广东2023下半年软考高级系统架构设计师报名时间&#xff1a;8月16日9:00-8月24日17:00 甘肃2023下半年软考高级系统架构设计师报名时间&am…

恢复idea删除的git本地文件

idea中删除git本地文件无法远程拉取pull已删除文件的问题 当前本地库处于另一个分支中&#xff0c;需将本分支Head重置&#xff0c;git 强行pull并覆盖本地文件 解决方式一&#xff1a; git fetch --all git reset --hard origin/master git pull解决方式二&#xff1a; git…

Docker基础——基础详解

仓库&#xff0c;镜像&#xff0c;容器的关系 Docker镜像 当运行容器时&#xff0c;使用的镜像如果在本地中不存在&#xff0c;docker 就会自动从 docker 镜像仓库中下载&#xff0c;默认是从 Docker Hub 公共镜像源下载 镜像列表 可以使用 docker images 来列出本地主机上的…

vue3,elementPlus和自己封装,点击 新增添加表单,删除表单,提交数据

ElementPlus下的form也有新增表单 如果你写H5等没找到合适的 自己也可以进行封装 实现3个代码讲解:1&#xff1a;ElementPlus的代码 2&#xff1a;自己书写的代码 3&#xff1a;自己把2的代码进行封装 1&#xff1a;ElementPlus的运行效果 点击提交 1&#xff1a;ElementPlus…

jieba和WordCloud

词云图像 import wordcloud import jieba import matplotlib.pyplot as plttext"中华人民共和国是伟大的国家,我最敬爱的祖国啊&#xff0c;你是美丽的花园" textjieba.lcut_for_search(text) text" ".join(text) wwordcloud.WordCloud(width1000,height8…

05 Docker 安装常用软件 (mongoDB)

目录 1. mongoDB简介 1.1 mongodb的优势 2. mongodb的安装 2.1 创建数据文件夹 2.2 备份日志 2.3 配置文件夹 2.4 创建两个文件 ---> 2.4.1 配置如下: 2.5 拉取mongodb 2.6 运行容器 2.7 进入mongodb容器 ---> 2.7.0 高版本(6.0)以上是这样的 , 旧版的没研究 …

我爱学QT--qt的网络编程

学习地址&#xff1a; QT网络编程之TCP通信_哔哩哔哩_bilibili QT网络编程有TCP和UDP。 TCP编程需要用到两个类&#xff1a;QTcpServer和QTcpSocket 本节课目标&#xff1a; 完成一个服务器和一个客户端 首先是经典的几步 先设计ui再设计逻辑实现 多看看写的文件理解吧

10.5.2 【Linux】命令执行的判断依据, ,||

cmd ; cmd &#xff08;不考虑指令相关性的连续指令下达&#xff09; 在某些时候&#xff0c;我们希望可以一次执行多个指令&#xff0c;例如在关机的时候我希望可以先执行两次sync 同步化写入磁盘后才 shutdown 计算机&#xff0c;那么可以这样作&#xff1a; [rootstudy ~]…

【信号去噪和分类】基于小波的隐马尔可夫模型统计信号处理(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

java学习路程之篇二、知识点、配置JAVA_HOME、跨平台、JVM、JRE、JDK

文章目录 1、Java背景介绍2、Java跨平台性3、JDK的下载和安装4、第一个Java程序5、HelloWorld案例详解6、JVM、JRE和JDK7、配置JAVA_HOME 1、Java背景介绍 2、Java跨平台性 3、JDK的下载和安装 4、第一个Java程序 5、HelloWorld案例详解 6、JVM、JRE和JDK 7、配置JAVA_HOME

MySQL表的约束与内置函数

目录 MySQL表的约束 空属性 默认值 列描述comment zerofill 主键 复合主键 自增长 唯一键 外键 MySQL的内置函数 日期函数 字符串函数 ​编辑数学函数 其他函数 MySQL表的约束 MySQL表的约束是用于规定表中数据的完整性和一致性的规则。 约束可以在创建表时定义&…

使用.LayUI实现动态选项卡Tab的强大功能

标题 正文&#xff1a;1.引入.LayUI框架文件2.创建选项卡容器3.初始化.LayUI组件和创建选项卡项以及获取数据准备3.1 Permission实体类3.2 PermissionDao类3.3 TreeVo类3.4 PermissionAction类 4.监听选项卡的切换事件5.运行和测试6.总结&#xff1a; 正文&#xff1a; 在Web界…

【导航地图DB】

地图DB概述 车载导航地图DB 主要侧重道路交通网&#xff0c;并从实用性、加快检索速度和减少数据容量的角度来考虑&#xff0c;有自己特有格式的电子地图。 含有空间位置地理坐标&#xff0c;能够与空间定位系统结合&#xff0c;准确引导人或交通工具从出发地到达目的地的电子…

ylb-接口10用户登录

总览&#xff1a; 在api模块下的service包&#xff0c;补充用户接口&#xff08;UserService&#xff09;&#xff1a;用户登录 package com.bjpowernode.api.service;import com.bjpowernode.api.model.User; import com.bjpowernode.api.pojo.UserAccountInfo;public inte…

运维小知识(三)——BIOS密码忘记怎么办(一键清除)

&#x1f349;&#x1f349;问题 为了防止恶意更改BIOS程序&#xff0c;一些人会设置BIOS密码&#xff0c;但这个密码若不常用的话会被人遗忘&#xff0c;或者一台旧电脑&#xff0c;需要重装系统&#xff0c;没有BIOS密码怎么办&#xff1f;有没有童靴遇到过&#xff0c;网上找…

bash脚本文件windows上的和linux上格式不同问题

脚本执行时报&#xff1a; syntax error: unexpected end of file&#xff0c;由于脚本是给定的。之前没有考虑这个问题&#xff0c;后查阅资料发现问题如下&#xff1a; 可能发生场景&#xff1a;windows环境编辑/生成的shell脚本&#xff0c;在linux系统上运行时报错 编辑和…

备战秋招009(20230714)

文章目录 前言一、Java内存区域1、JVM组成部分2、运行时数据区域01、基础02、程序计数器03、虚拟机栈04、本地方法栈05、堆06、方法区07、直接内存 3、HotSpot虚拟机对象01、对象的创建02、内存分配03、内存布局04、访问定位 二、垃圾回收1、堆空间01、空间结构02、GC 分类03、…