Spring-Bean 作用域

ops/2024/10/20 5:24:40/

作用域

在这里插入图片描述

作用域案例

java">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 如果为集合类型,则单例和原型对象各一个

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

java">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完全管理,不会执行销毁方法

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

java">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

java">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 查找方式

java">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.ppmy.cn/ops/39655.html

相关文章

如何防止WordPress网站内容被抓取

最近在检查网站服务器的访问日志的时候&#xff0c;发现了大量来自同一个IP地址的的请求&#xff0c;用站长工具分析确认了我的网站内容确实是被他人的网站抓取了&#xff0c;我第一时间联系了对方网站的服务器提供商投诉了该网站&#xff0c;要求对方停止侵权行为&#xff0c;…

如何使用google.protobuf.Struct?

google.golang.org/protobuf/types/known/structpb 包提供了一种方式来创建和操作 google.protobuf.Struct 类型的数据。google.protobuf.Struct 是一种灵活的数据类型&#xff0c;可以表示任何结构化数据。 以下是如何使用 structpb 包的一些示例&#xff1a; 创建 Struct&a…

高斯数据库创建函数的语法

CREATE FUNCTION 语法格式 •兼容PostgreSQL风格的创建自定义函数语法。 CREATE [ OR REPLACE ] FUNCTION function_name ( [ { argname [ argmode ] argtype [ { DEFAULT | : | } expression ]} [, …] ] ) [ RETURNS rettype [ DETERMINISTIC ] | RETURNS TABLE ( { column_…

Linux函数

目录 一、脚本函数 1.1 创建函数 1.2 使用函数 二、函数返回值 2.1 默认的退出状态码 2.2 使用return命令 2.3 使用函数输出 三、在函数中使用变量 3.1 向函数传达参数 3.2 在函数中处理变量 四、数组变量和函数 4.1 向函数中传递数组 4.2 从函数中返回数组 五、函数…

【数组算法】598. 区间加法

给你一个 m x n 的矩阵 M 和一个操作数组 op 。矩阵初始化时所有的单元格都为 0 。ops[i] [ai, bi] 意味着当所有的 0 < x < ai 和 0 < y < bi 时&#xff0c; M[x][y] 应该加 1。 在 执行完所有操作后 &#xff0c;计算并返回 矩阵中最大整数的个数 。 示例 1: …

探索全球静态住宅IP:网络新时代的稳定基石

在数字化浪潮席卷全球的今天&#xff0c;互联网已成为人们生活中不可或缺的一部分。随着网络技术的飞速发展&#xff0c;IP地址作为网络连接的标识符&#xff0c;其重要性日益凸显。特别是在对稳定性和安全性要求极高的应用场景中&#xff0c;全球静态住宅IP凭借其独特的优势&a…

shopee虾皮跨境商家:月出1000单爆款打造思路!

Shopee爆款打造的方式是需要满足很多特点的&#xff0c;我把它大概归结为了7大要素&#xff1a; 1、顺应平台潮流 通过Shopee前台、市场周报&#xff0c;以及你对这个行业的经验&#xff0c;能够及时掌握平台最近主推产品的信息&#xff0c;又刚好我们店铺里面的商品有能够搭…

matlab中的引导滤波函数imguidedfilter()

在MATLAB中&#xff0c;可以使用imguidedfilter函数进行引导滤波。该函数的语法如下&#xff1a; output imguidedfilter(input, guidance, varargin)其中&#xff0c;input是待滤波的图像&#xff0c;guidance是用来引导滤波的图像&#xff08;通常是原始图像或其它相关信息…