Spring-Bean 作用域

作用域

在这里插入图片描述

作用域案例

public class BeanScopeDemo {
    @Autowired
    @Qualifier("singletonPerson")
    Person person;

    @Autowired
    @Qualifier("prototypePerson")
    Person person1;

    @Autowired
    @Qualifier("prototypePerson")
    Person person2;

    @Autowired
    Set<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
     */
    @Bean
    public 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;
    @Override
    public 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;
    }
    @PostConstruct
    public void init() {
        System.out.println(this.beanName + " : init execute");
    }
    @PreDestroy
    public void destroy() {
        System.out.println(this.beanName + " : destroy execute");
    }

    @Override
    public 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;

    @Autowired
    Map<String, Person> personMap;
    @Autowired
    ConfigurableListableBeanFactory 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
     */
    @Bean
    public static Person singletonPerson() {
        return createPerson();
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public static Person prototypePerson() {
        return createPerson();
    }

    @Autowired
    ConfigurableListableBeanFactory beanFactory;
    @Override
    public 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();
    }
    @Override
    public 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;
    }
    @Override
    public Object remove(String name) {
        return getContext().remove(name);
    }
    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
        remove(name);
    }
    @Override
    public Object resolveContextualObject(String key) {
        return getContext().get(key);
    }
    @Override
    public 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
参考资料:小马哥核心编程思想

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

perf 中的 cpu-cycles event 介绍

perf 中的 cpu-cycles event 介绍 cycles简介 cycles事件记录处理器核心执行的时钟周期数。每个时钟周期代表处理器内部时钟振荡器的一个周期。这个事件通常用于衡量处理器的执行速度&#xff0c;因为它直接反映了指令执行所需的时间。一个较高的cycles计数可能意味着代码执行…

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

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

Blender细节补充

1.饼状菜单&#xff0c;用于快速切换/选择 例如&#xff1a; ~&#xff1a;切换视图 Z&#xff1a;切换着色方式 &#xff0c;&#xff1a;切换坐标系 .&#xff1a;切换基准点 Shift S&#xff1a;吸附 有两种使用方式&#xff1a; -点选 -滑选&#xff0c;按快捷键…

在Tiled中制作动画瓦片图

什么是瓦片图&#xff1f;瓦片图是指用图块把游戏场景评出来 工具安装链接&#xff1a;Tiled | Flexible level editor 资源下载教程 资源下载&#xff1a;Mystic Woods - 16x16 Pixel Art Asset Pack by Game Endeavor 解压后得到一些资源 新建图块集合 Tiled的安装就不介绍…

Nginx或Tengine服务器配置SSL证书

目录 前提条件 步骤一&#xff1a;下载SSL证书 步骤二&#xff1a;在Nginx服务器安装证书 步骤三&#xff1a;验证SSL证书是否配置成功 前提条件 已通过数字证书管理服务控制台签发证书SSL证书绑定的域名已完成DNS解析&#xff0c;即您的域名与主机IP地址相互映射已在Web服…

全志ARM-SG90舵机

控制转角 向黄色信号线“灌入”PWM信号。 PWM波的频率不能太高&#xff0c;50hz&#xff0c;即周期1/频率1/500.02s&#xff0c;20ms左右数据&#xff1a; 不同的PWM波形对应不同的旋转角度&#xff0c;以20ms为周期&#xff0c;50hz为频率的PWM波 定时器需要定时20ms,关心的单…

Ubuntu24安装搜狗输入法,修复闪屏问题

下载deb安装包&#xff1a;搜狗输入法linux-首页 安装&#xff1a;sudo dpkg -i 1.deb 搜狗输入法linux-安装指导 重启&#xff0c;但是完成后闪烁。按以下步骤更改桌面配置。 sudo gedit /etc/gdm3/custom.conf 取消WaylandEnable的注释即可

Python 函数式编程

匿名函数 Python 允许用 lambda 关键字创造匿名函数。匿名顾名思义就是没有名字&#xff0c;即不需要以标准的方式来声明&#xff0c;比如说&#xff0c;使用 def 加函数名来声明。一个完整的 lambda “语句”代表了一个表达式&#xff0c;这个表达式的定义体必须和声明放在同…

CountDownLatch应用场景代码练习

目录 概念原理核心参数和方法两种应用场景实现代码应用一&#xff1a;让 主任务 等待 所有子任务执行完毕后&#xff0c;再继续执行执行结果应用二&#xff1a;让所有子任务同时执行&#xff0c;打印出发时间执行结果应用二&#xff08;扩展&#xff09;&#xff1a;让所有子任…

[沫忘录]MySQL 锁

[沫忘录]MySQL 锁 锁能够协调多线程或多进程并发访问某资源产生的数据冲突与错乱。而在数据库中&#xff0c;锁也是协调数据库访问的有效工具。 全局锁 能够锁住当前服务器所有数据库及其表。后续所有事务都只能进行读操作&#xff0c;而不能进行写操作或表属性更改。 典型…

C++入门系列-析构函数

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 析构函数 概念 析构函数&#xff0c;与构造函数功能相反&#xff0c;析构函数不是完成对对象本身的销毁&#xff0c;局部对象销毁工作是由编译器完成的&#xff0c;而对象在销…

即插即用篇 | YOLOv8 引入 Strip Pooling | 重新思考场景解析的空间池化

本改进已集成到 YOLOv8-Magic 框架。 空间池化已被证明在捕获像素级预测任务的长距离上下文信息方面非常有效,如场景解析。在本文中,我们超越了通常具有N N规则形状的常规空间池化,重新思考空间池化的构成,引入了一种新的池化策略,称为条带池化,它考虑了一个长而窄的核,…

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

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

ES6-自学01

调用方法读取文件&#xff1a;如果失败就throw抛出err,成功则抛出data 2.使用promise封装&#xff0c;如果失败就改变状态为 reject(err) 如果成功就 resolve(返回成功的值) &#xff0c;然后then,就可以获取返回的值&#xff0c;值toString&#xff08;&#xff09;方法来把…

示例十一、声音传感器

通过以下几个示例来具体展开学习,了解声音传感器原理及特性&#xff0c;学习声音传感器的应用&#xff08;干货版&#xff09;&#xff1a; 示例十一、声音传感器 ino文件源码&#xff1a; //Arduino C demo void setup() {Serial.begin(9600);pinMode(5, OUTPUT); }void loo…

解决wangEditor使用keep-alive缓存后,调用editor.cmd.do()失败

前提&#xff1a;wangeditor版本&#xff1a;4.7.11 vue版本&#xff1a;vue2 问题&#xff1a;在使用wangeditor富文本编辑器时&#xff0c;需求需要通过点击一个按钮&#xff0c;手动插入定义好的内容&#xff0c;所以使用了 editor.cmd.do(insertHTML, ....) 方法新增…

steam_api64.dll是什么东西?steam_api64.dll缺失的多个详细解决方法

在现代PC游戏领域&#xff0c;Steam无疑是最具影响力的游戏分发和社交平台之一。它不仅提供了一个庞大的游戏市场&#xff0c;还集成了好友系统、成就系统、云存储等多种功能&#xff0c;为数百万玩家提供了便捷的游戏体验。在这庞大的生态系统中&#xff0c;steam_api64.dll作…

快递物流查询:如何实现快递批量查询?这些技巧助你轻松应对

在日常生活和工作中&#xff0c;我们经常需要查询快递物流信息&#xff0c;尤其是当面对大量的快递包裹时&#xff0c;逐一查询无疑会耗费大量的时间和精力。这时&#xff0c;实现快递批量查询就显得尤为重要。本文将为你介绍办公提效工具一些实现快递批量查询的技巧&#xff0…

基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (一)

基于LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; RAG 是未来人工智能应用的基石。大家并不是在寻求仅仅产生无意义反应的人工智能。而目标是人工智能能够从特定文档集中检索答案&#xff0c;理解查询的上下文&#xff0c;指导自己搜索其嵌入内容或…

嵌入式C语言高级教程:实现基于STM32的智能健康监测手环

智能健康监测手环能够实时监控用户的生理参数&#xff0c;如心率、体温和活动量&#xff0c;对于健康管理和疾病预防非常有帮助。本教程将指导您如何在STM32微控制器上实现一个基本的智能健康监测手环。 一、开发环境准备 硬件要求 微控制器&#xff1a;STM32L476RG&#xf…