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.hqwc.cn/news/689653.html

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

相关文章

FFmpeg常用API与示例(四)——过滤器实战

1.filter 在多媒体处理中&#xff0c;filter 的意思是被编码到输出文件之前用来修改输入文件内容的一个软件工具。如&#xff1a;视频翻转&#xff0c;旋转&#xff0c;缩放等。 语法&#xff1a;[input_link_label1]… filter_nameparameters [output_link_label1]… 1、视…

住宅ip与数据中心ip代理的区别是什么

代理通常意味着“替代”。它是用户设备和目标服务器之间的中介&#xff0c;允许在不同的IP地址下上网。代理ip根据来源分类可分住宅ip与数据中心ip&#xff0c;二者之间区别是什么呢&#xff1f; 住宅ip是由互联网服务提供商(ISP)提供给家庭的IP地址。出于这个原因&#xff0c…

笨方法自学python(三)-数学计算

数字和数学计算 这章练习里有很多的数学运算符号。我们来看一遍它们都叫什么名字 plus 加号-minus 减号/ slash 斜杠*asterisk 星号% percent 百分号< less-than 小于号greater-than 大于号< less-than-equal 小于等于号 greater-than-equal 大于等于号 print ("I …

LeetCode/NowCoder-链表经典算法OJ练习1

目录 说在前面 题目一&#xff1a;移除链表元素 题目二&#xff1a;反转链表 题目三&#xff1a;合并两个有序链表 题目四&#xff1a;链表的中间节点 SUMUP结尾 说在前面 dear朋友们大家好&#xff01;&#x1f496;&#x1f496;&#x1f496;数据结构的学习离不开刷题…

企业网络需求及适合的解决方案

近年来&#xff0c;企业网络通信需求可谓五花八门&#xff0c;变幻莫测。它不仅为企业的生产、办公、研发、销售提供全面赋能&#xff0c;同时也让企业业务规模变大成为了可能。 在当前的技术格局下&#xff0c;中大型企业常见的技术方案有很多&#xff0c;而同时也有各自不可替…

【2024亚马逊云科技峰会】Amazon Bedrock + Llama3 生成式AI实践

在 4 月 18 日&#xff0c;Meta在官网上公布了旗下最新大模型Llama 3。目前&#xff0c;Llama 3已经开放了80亿&#xff08;8B&#xff09;和700亿&#xff08;70B&#xff09;两个小参数版本&#xff0c;上下文窗口为8k&#xff0c;据称&#xff0c;通过使用更高质量的训练数据…

零代码平台助力中国石化江苏油田实现高效评价体系

概述&#xff1a; 中国石化集团江苏石油勘探局有限公司面临着评价体系依赖人工处理数据、计算繁琐且容易出错的挑战。为解决这一问题&#xff0c;他们决定借助零代码平台明道云开发江苏油田高质量发展经济指标评价系统。该系统旨在实现原始数据批量导入与在线管理、权重及评分…

线路和绕组中的波过程(三)

本篇为本科课程《高电压工程基础》的笔记。 本篇为这一单元的第三篇笔记。上一篇传送门。 冲击电晕对线路上波过程的影响 实际中的导线存在电阻&#xff0c;而且还有对地电导&#xff0c;会消耗一部分能量。但是因为雷击所涉及的传输距离很短&#xff0c;所以几乎可以忽略这…

39-5 入侵检测系统(IDS)- 安装配置IDS(注意我没安装成功,阅读需谨慎)

官网:Snort Rules and IDS Software Download 参考: (这位大佬分享了安装包下载链接):https://www.cnblogs.com/taoyuanming/p/12722263.html (安装过程参考这位大佬):Snort 安装与配置(CentOS 7)_centos 7 snort-CSDN博客一、安装 IDS(我这里在 CentOS 7 虚拟机中安…

iOS Failed to create provisioning profile.

错误描述 错误情况参考这张图 解决方案 修改Bundle Identifier就可以解决这个错误&#xff0c;找不到位置可以看图 &#xff08;具体解决的原理与证书有关&#xff0c;个人不是非常熟悉&#xff0c;还望大神告知&#xff09;

[优选算法]------滑动窗⼝——209. 长度最小的子数组

目录 1.题目 1.解法⼀&#xff08;暴⼒求解&#xff09;&#xff08;会超时&#xff09;&#xff1a; 2.解法⼆&#xff08;滑动窗⼝&#xff09;&#xff1a; 1.算法思路&#xff1a; 2.手撕图解 3.代码实现 1.C 2.C语言 1.题目 209. 长度最小的子数组 给定一个含有 n…

C语言----斐波那契数列

各位看官们好&#xff0c;当我写了上一篇博客杨辉三角后&#xff0c;有一些看官叫我讲一下斐波那契数列。对于这个大家应该是有了解的。最简单的规律就是f(n)f(n-2)f(n-1)。就是当前是前两项之和&#xff0c;然后下标1和0都是1.从第三项开始计算的。那么我们知道规律&#xff0…