Spring-Bean 作用域

作用域

在这里插入图片描述

作用域案例

public class BeanScopeDemo {@Autowired@Qualifier("singletonPerson")Person person;@Autowired@Qualifier("prototypePerson")Person person1;@Autowired@Qualifier("prototypePerson")Person person2;@AutowiredSet<Person> personSet;/*** 创建bean* @return*/public static Person createPerson(){Person person = new Person();person.setId(System.currentTimeMillis());person.setName(System.currentTimeMillis()+"");return person;}/*** 查找* @param context*/public static void scopeBeanLookUp(AnnotationConfigApplicationContext context){for (int i = 0; i < 3; i++) {Person prototypePerson = context.getBean("prototypePerson", Person.class);System.out.println("prototypePerson" + prototypePerson);Person singletonPerson = context.getBean("singletonPerson", Person.class);System.out.println("singletonPerson" + singletonPerson);}}private static void scopedBeansByInjection(AnnotationConfigApplicationContext context) {BeanScopeDemo bean = context.getBean(BeanScopeDemo.class);System.out.println(bean.person);System.out.println(bean.person1);System.out.println(bean.person2);System.out.println(bean.personSet);}public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(BeanScopeDemo.class);context.refresh();scopeBeanLookUp(context);scopedBeansByInjection(context);context.close();}/*** 默认scope 就是singleton* @return*/@Beanpublic static Person singletonPerson(){return createPerson();}@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public static Person prototypePerson(){return createPerson();}
}

运行结果:
在这里插入图片描述
结论:
1 singleton Bean 无论依赖查找还是依赖注入,均为同一个对象
2 prototype Bean 无论依赖查找还是依赖注入,均为新生成的对象
3 如果为集合类型,则单例和原型对象各一个

单例模式和原型模式生命周期的不同

public class Person implements BeanNameAware {private Long id;private String name;/*** 不需要序列化*/private transient String beanName;@Overridepublic String toString() {return "Person{" +"id=" + id +", name='" + name + '\'' +'}';}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@PostConstructpublic void init() {System.out.println(this.beanName + " : init execute");}@PreDestroypublic void destroy() {System.out.println(this.beanName + " : destroy execute");}@Overridepublic void setBeanName(String name) {this.beanName = name;}
}

改造Person以后我们继续调用上面的方法:
在这里插入图片描述
我们可以得到下面的结论:
1 原型和单例模式都是会执行postconstruct
2 原型模式的生命周期不能被spring完全管理,不会执行销毁方法

如果我们需要销毁,采用下面这种方式来操作

public class BeanScopeDemo implements DisposableBean {@Autowired@Qualifier("singletonPerson")Person person;@Autowired@Qualifier("prototypePerson")Person person1;@Autowired@Qualifier("prototypePerson")Person person2;@AutowiredMap<String, Person> personMap;@AutowiredConfigurableListableBeanFactory beanFactory;/*** 创建bean** @return*/public static Person createPerson() {Person person = new Person();person.setId(System.currentTimeMillis());person.setName(System.currentTimeMillis() + "");return person;}/*** 查找** @param context*/public static void scopeBeanLookUp(AnnotationConfigApplicationContext context) {for (int i = 0; i < 3; i++) {Person prototypePerson = context.getBean("prototypePerson", Person.class);System.out.println("prototypePerson" + prototypePerson);Person singletonPerson = context.getBean("singletonPerson", Person.class);System.out.println("singletonPerson" + singletonPerson);}}private static void scopedBeansByInjection(AnnotationConfigApplicationContext context) {BeanScopeDemo bean = context.getBean(BeanScopeDemo.class);System.out.println(bean.person);System.out.println(bean.person1);System.out.println(bean.person2);System.out.println(bean.personMap);}public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(BeanScopeDemo.class);context.refresh();scopeBeanLookUp(context);scopedBeansByInjection(context);context.close();}/*** 默认scope 就是singleton** @return*/@Beanpublic static Person singletonPerson() {return createPerson();}@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public static Person prototypePerson() {return createPerson();}@AutowiredConfigurableListableBeanFactory beanFactory;@Overridepublic void destroy() throws Exception {this.person1.destroy();this.person2.destroy();for (Map.Entry<String, Person> entry : this.personMap.entrySet()) {String key = entry.getKey();BeanDefinition bd = beanFactory.getBeanDefinition(key);if (bd.isPrototype()) {entry.getValue().destroy();}}}
}

运行结果:
在这里插入图片描述
可以看到原型模式的对象也被销毁了。

自定义Scope

1 首先自定义Scope

public class ThreadLocalScope implements Scope {public static final String SCOPE_NAME = "thread_local";private NamedThreadLocal<Map<String, Object>> threadLocal = new NamedThreadLocal<Map<String, Object>>("thread-local-scope") {public Map<String, Object> initialValue() {return new HashMap<>();}};private Map<String, Object> getContext() {return threadLocal.get();}@Overridepublic Object get(String name, ObjectFactory<?> objectFactory) {Map<String, Object> context = getContext();Object object = context.get(name);if (object == null) {object = objectFactory.getObject();context.put(name, object);}return object;}@Overridepublic Object remove(String name) {return getContext().remove(name);}@Overridepublic void registerDestructionCallback(String name, Runnable callback) {remove(name);}@Overridepublic Object resolveContextualObject(String key) {return getContext().get(key);}@Overridepublic String getConversationId() {return Thread.currentThread().getName();}
}

2 查找方式

public class ThreadLocalScopeDemo {/*** 默认scope 就是singleton** @return*/@Bean@Scope(ThreadLocalScope.SCOPE_NAME)public static Person singletonPerson() {return createPerson();}/*** 创建bean** @return*/public static Person createPerson() {Person person = new Person();person.setId(System.currentTimeMillis());person.setName(System.currentTimeMillis() + "");return person;}public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(ThreadLocalScopeDemo.class);// 注册工厂 也就是 ThreadLocalScope.SCOPE_NAME 这个注入会走这里context.addBeanFactoryPostProcessor(beanFactory -> {beanFactory.registerScope(ThreadLocalScope.SCOPE_NAME, new ThreadLocalScope());});context.refresh();scopeBeansLookUp(context);context.close();}private static void scopeBeansLookUp(ApplicationContext context) {// 这里开启三个现场去查找for (int i = 0; i < 3; i ++) {Thread thread = new Thread(() -> {Person person = context.getBean( Person.class);System.out.println(Thread.currentThread().getId()+ " : " + person);});thread.start();try {thread.join();} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

结果:
在这里插入图片描述
也就几说我们可以减少对象的创建因为我们在Threadlocal里面存储了,所以线程内部是可以复用的,不存在线程安全问题。
比如SimpleDateFormat是非线程安全的,所以可以采用这种方式来实现。

拓展提示:SpingCloud中的@RefreshScope
参考资料:小马哥核心编程思想

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

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

相关文章

程序环境和预处理、编译链接过程、编译的几个阶段、运行环境、预定义符号等的介绍

文章目录 前言一、程序的翻译环境和执行环境二、编译链接过程三、编译的几个阶段四、运行环境五、预定义符号总结 前言 程序环境和预处理、编译链接过程、编译的几个阶段、运行环境、预定义符号的介绍。 一、程序的翻译环境和执行环境 在 ANSI C 的任何一种实现中&#xff0c…

CLIP 浅析

CLIP 浅析 文章目录 CLIP 浅析概述如何训练CLIP如何使用Clip进行图像分类优缺点分析优点缺点 概述 CLIP的英文全称是Contrastive Language-Image Pre-training&#xff0c;即一种基于对比文本-图像对的预训练方法或者模型。 如何训练CLIP CLIP包括两个模型&#xff1a;Text …

【数据结构】顺序表与链表的差异

顺序表和链表都是线性表&#xff0c;它们有着相似的部分&#xff0c;但是同时也有着很大的差异。 存储空间上的差异&#xff1a; 对于插入上的不同点&#xff0c;顺序表在空间不够时需要扩容&#xff0c;而如果在使用realloc函数去扩容&#xff0c;会有原地扩容和异地扩容两种情…

Spring Security基础教程:从入门到实战

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c…

电脑复制和粘贴的时候会出现Hello!

电脑不管是Microsoft Excel还是Microsoft Word复制之后粘贴过来就出现HELLO&#xff0c;当复制粘贴文件的时候就会出现WINFILE&#xff1b; 具体现象看下面两个图片&#xff1a; 这是因为winfile 文件病毒&#xff08;幽灵蠕虫病毒&#xff09;,每月的28号发作&#xff1b; 症状…

wangEditor富文本编辑器与layui图片上传

记录&#xff1a;js 显示默认的wangEditor富文本编辑器内容和图片 <style>body {background-color: #ffffff;}.layui-form-select dl{z-index:100000;} </style> <div class"layui-form layuimini-form"><div class"layui-form-item"…

ubuntu系统在有无NVIDIA驱动下查看显卡型号

在ubuntu系统下&#xff0c;分别在有nvidia显卡驱动和无nvidia显卡驱动时&#xff0c;查看nvidia显卡型号。 1、有nvidia显卡驱动时的查看方式 nvidia-smi -L会显示如下信息&#xff1a; GPU 0: NVIDIA GEForce GTX 1660 SUPER (UUID: GPU-*****)2、无nvidia显卡驱动时的查看…

【Linux】从零开始认识动静态库 -动态库

送给大家一句话&#xff1a; 我不要你风生虎啸&#xff0c; 我愿你老来无事饱加餐。 – 梁实秋 《我把活着欢喜过了》 ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚ଘ(੭ˊᵕˋ)੭…

架构每日一学 4:成为首席架构师,你必须学会顺应人性

本文首发于公众平台&#xff1a;腐烂的橘子 架构师生存法则之二&#xff1a;架构活动需要顺应人性 程序员入行的第一天起就进入了一个机器的世界。在别人的眼中&#xff0c;程序员平时很少说话&#xff0c;更多的时间在和电脑打交道。 程序员工作时间久了大脑会被格式化&…

Java医院绩效考核系统源码B/S+avue+MySQL助力医院实现精细化管理 医院综合绩效核算系统源码

Java医院绩效考核系统源码B/SavueMySQL助力医院实现精细化管理 医院综合绩效核算系统源码 医院绩效考核系统目标是实现对科室、病区财务指标、客户指标、流程指标、成长指标的全面考核、分析&#xff0c;并与奖金分配、学科建设水平评价挂钩。 具体功能模块包括收入核算、成本…

Python中tkinter编程入门3

在使用tkinter创建了窗口之后&#xff0c;可以将一些控件“放置”到窗口中。这些控件包括标签、按键以及输入框等。 1 在窗口中“放置”标签 在窗口中“放置”标签主要有两个步骤&#xff0c;一是创建标签控件&#xff0c;二是将创建好的标签“放置”到窗口上。 1.1 创建标签…

P8803 [蓝桥杯 2022 国 B] 费用报销

P8803 [蓝桥杯 2022 国 B] 费用报销 分析 最值问题——DP 题意分析&#xff1a;从N张票据中选&#xff0c;且总价值不超过M的票据的最大价值&#xff08;背包问题&#xff09; K天限制 一、处理K天限制&#xff1a; 1.对于输入的是月 日的格式&#xff0c;很常用的方式是…

AI算法工程师课程学习-数学基础-高数1-微积分

机器学习数学基础学习路线&#xff1a;1.高中数学-->大学2.微积分-->3.线性代数-->4.概率论-->5.优化理论。 为尽快进入到AI算法课程的学习&#xff0c;现在高数的学习要求&#xff1a; 1.看得懂&#xff0c;知道是什么&#xff0c;能听得懂&#xff0c;能理解讲…

RabbitMQ(安装配置以及与SpringBoot整合)

文章目录 1.基本介绍2.Linux下安装配置RabbitMQ1.安装erlang环境1.将文件上传到/opt目录下2.进入/opt目录下&#xff0c;然后安装 2.安装RabbitMQ1.进入/opt目录&#xff0c;安装所需依赖2.安装MQ 3.基本配置1.启动MQ2.查看MQ状态3.安装web管理插件4.安装web管理插件超时的解决…

【VTKExamples::Rendering】第五期 环形阵列Rotations

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例环形阵列Rotations,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. Rotations

C语言例题35、反向输出字符串(指针方式),例如:输入abcde,输出edcba

#include <stdio.h>void reverse(char *p) {int len 0;while (*p ! \0) { //取得字符串长度p;len;}while (len > 0) { //反向打印到终端printf("%c", *--p);len--;} }int main() {char s[255];printf("请输入一个字符串&#xff1a;");gets(s)…

基恩士PLC-KV5500基础入门

一、准备工作&#xff1a; 1.准备的东西&#xff1a;一个基恩士PLC-KV5500模块。两个自复位开关&#xff0c;24v LED灯一个&#xff0c;24v开关电源一个&#xff0c;KV5500端子台IO线缆&#xff1b;有编程软件的电脑一台。 编程软件&#xff1a; 基恩士PLC-KV5500接线图&…

LeetCode-258. 各位相加【数学 数论 模拟】

LeetCode-258. 各位相加【数学 数论 模拟】 题目描述&#xff1a;解题思路一&#xff1a;循环解题思路二&#xff1a;进阶 O(1)解题思路三&#xff1a; 题目描述&#xff1a; 给定一个非负整数 num&#xff0c;反复将各个位上的数字相加&#xff0c;直到结果为一位数。返回这个…

力扣/leetcode383.比特位记数

题目描述 给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 示例 代码思路 第一种方法 最简单的方法就是&#xff0c;遍历然后使用python自带的bin()方法直接…

视频合并有妙招:视频剪辑一键操作,批量嵌套合并的必学技巧

在数字时代的今天&#xff0c;视频已经成为我们日常生活和工作中不可或缺的一部分。无论是记录生活点滴&#xff0c;还是制作专业项目&#xff0c;视频合并都是一个常见的需求。然而&#xff0c;对于许多人来说&#xff0c;视频合并却是一个复杂且繁琐的过程。现在有云炫AI智剪…