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…

解决了这个报错User{code: 0, msg: ‘params pid Missing‘, time: ‘1715421706‘, data: null}

这个报错的意思是参数 pid 缺失。在你的代码中&#xff0c;有一个请求或操作需要传递参数 pid&#xff0c;但是没有正确传递或设置这个参数&#xff0c;导致系统无法识别或处理这个请求。 要解决这个问题&#xff0c;你可以检查代码中是否有包含需要传递 pid 参数的请求或操作…

知识付费系统源码定制开发,政策规范后的研学旅行要如何发展?

9月&#xff0c;武汉市旅游发展委员会联合武汉市教育局公布《服务机构评定与服务规范》、《研学基地评定与服务规范》和《研学导师评定与服务规范》3个考评标准&#xff0c;对武汉市中小学生研学旅行标准作出了详细规定。 在此之后&#xff0c;广东省发布《关于推进中小学生研学…

BigDecimal类型引用传递

在Java中,所有的对象包括BigDecimal都是通过引用传递的。这意味着当你将一个对象作为参数传递给一个方法时,实际上传递的是这个对象在内存中的地址(引用),而不是对象本身。因此,如果方法内部对这个引用所指向的对象进行了修改,那么方法外部的原始对象也会受到这个修改的…

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; 症状…

Ajax原理是什么,怎么实现?

Ajax是在不需要重新加载整个网页的情况下&#xff0c;与服务器交换数据并且更新部分网页的技术。 Ajax的原理就是通过XMLHttpRequest对象来向服务器发起异步请求&#xff0c;从服务器获取数据&#xff0c;然后用JavaScript来操作DOM实现更新页面。 实现Ajax异步交互&#xff…

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管理插件超时的解决…

构建C语言静态库文件并调用的实战案例和详细步骤实现

准备源文件 calc.h 定义加法&#xff1a;int add(int a, int b);定义减法&#xff1a;int sub(int a, int b); #ifndef __CALC_H_ #define __CALC_H_int add(int a, int b); int sub(int a, int b);#endif // __CALC_H_calc.c 简单的实现加法简单的实现减法 #include &quo…

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

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