【Spring6】| Bean的作用域

news/2024/7/8 6:28:31

目录

一:Bean的作用域

1. singleton(单例)

2. prototype(多例)

3. 其它scope

4. 自定义scop(了解)


一:Bean的作用域

1. singleton(单例)

(1)默认情况下,Spring的IoC容器创建的Bean对象是单例的(singleton)!

在Spring上下文对象初始化的时候实例化!

SpringBean类

package com.bjpowernode.spring6.bean;

public class SpringBean {
}

spring-scop.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="springBean" class="com.bjpowernode.spring6.bean.SpringBean"/>
</beans>

测试程序

package com.bjpowernode.spring6.test;

import com.bjpowernode.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScopTest {
    @Test
    public void testScop(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scop.xml");
        SpringBean sb1 = applicationContext.getBean("springBean", SpringBean.class);
        System.out.println(sb1);
        // 访问同一个对象
        SpringBean sb2 = applicationContext.getBean("springBean", SpringBean.class);
        System.out.println(sb2);
    }
}

执行结果:

通过测试验证:Spring的IoC容器中,默认情况下,Bean对象是单例的!

 (2)这个对象在什么时候创建的呢?

可以为SpringBean提供一个无参数构造方法,进行测试:

SpringBean类

package com.bjpowernode.spring6.bean;

public class SpringBean {
    public SpringBean() {
        System.out.println("SpringBean的无参数构造方法执行了!");
    }
}

将测试程序中getBean()所在行代码注释掉

package com.bjpowernode.spring6.test;

import com.bjpowernode.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScopTest {
    @Test
    public void testScop(){
        new ClassPathXmlApplicationContext("spring-scop.xml");
    }
}

执行结果:

通过测试得知,默认情况下,Bean对象的创建是在初始化Spring上下文的时候就完成的

调用getBean方法只是从Map集合当中取出数据!

2. prototype(多例)

(1)那么就要创建多例的怎么办呢?

如果想让Spring的Bean对象以多例的形式存在,可以bean标签中指定scope属性的值为:prototype(原型、多例)!

spring-scop.xml配置

增加了scope属性,目前来说scope属性有两个值:
第一个值:singleton 单例(默认情况下不设置就是单例的)
第二个值:prototype 原型/多例

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="springBean" class="com.bjpowernode.spring6.bean.SpringBean" scope="prototype"/>
</beans>

执行结果:

得到两次创建的内存地址就不一样了,多例!

 (2)此时是什么时候创建对象呢?

在初始化上下文对象时不会创建对象,每一次执行getBean()方法的时候创建Bean对象,调用几次则创建几次!

SpringBean类

package com.bjpowernode.spring6.bean;

public class SpringBean {
    public SpringBean() {
        System.out.println("SpringBean的无参数构造方法执行了!");
    }
}

将测试程序中getBean()所在行代码注释掉

package com.bjpowernode.spring6.test;

import com.bjpowernode.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScopTest {
    @Test
    public void testScop(){
        new ClassPathXmlApplicationContext("spring-scop.xml");
    }
}

执行结果:

此时并没有执行构造方法,通过测试验证确实是调用getBean方法的时候创建对象

3. 其它scope

scope属性的值不止两个,它一共包括8个选项:

singleton:默认的,单例。

prototype:原型。每调用一次getBean()方法则获取一个新的Bean对象,或每次注入的时候都是新对象。

request:一个请求对应一个Bean仅限于在WEB应用中使用

session:一个会话对应一个Bean仅限于在WEB应用中使用

global session:portlet应用中专用的。如果在Servlet的WEB应用中使用global session的话,和session一个效果。(portlet和servlet都是规范。servlet运行在servlet容器中,例如Tomcat。portlet运行在portlet容器中。)

application:一个应用对应一个Bean仅限于在WEB应用中使用。

websocket:一个websocket生命周期对应一个Bean仅限于在WEB应用中使用。

自定义scope:很少使用。

例如:在pom.xml文件当中引入web的框架springmvc

<!--引入web的框架,例如springmvc-->
 <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>6.0.0-M2</version>
</dependency>

此时的scop值就可以使用request和session的值

4. 自定义scop(了解)

接下来自定义一个Scope,线程级别的Scope!

在同一个线程中,获取的Bean都是同一个;如果是跨线程则是不同的对象!

(1)先测试单例模式下开启多线程创建的是几个Bean对象

package com.bjpowernode.spring6.test;

import com.bjpowernode.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringScopTest {
    @Test
    public void testThradScop(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scop.xml");
        // 主线程
        SpringBean sb1 = applicationContext.getBean("springBean", SpringBean.class);
        System.out.println(sb1);
        SpringBean sb2 = applicationContext.getBean("springBean", SpringBean.class);
        System.out.println(sb2);

        // 启动一个新的线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                SpringBean sb3 = applicationContext.getBean("springBean", SpringBean.class);
                System.out.println(sb3);
                SpringBean sb4 = applicationContext.getBean("springBean", SpringBean.class);
                System.out.println(sb4);
            }
        }).start();
    }
}

测试结果:单例模式,拿到的都是同一个Bean对象

 

(2)测试自定义scop

第一步:自定义Scope(实现Scope接口)

实际上spring内置了线程范围的类:org.springframework.context.support.SimpleThreadScope,可以直接用!

第二步:将自定义的Scope注册到Spring容器中

注册的时候需要用到自定义范围配置器CustomScopeConfigurer(自定义范围配置器)

 <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="threadScop">
                    <!--这个Scope接口的实现类使用的是Spring框架内置的,也可以自定义。-->
                    <bean class="org.springframework.context.support.SimpleThreadScope"/>
                </entry>
            </map>
        </property>
    </bean>

第三步:使用Scope

<bean id="springBean" class="com.bjpowernode.spring6.bean.SpringBean" scope="threadScop"/>

完整的spring-cope.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--先开启自定义范围配置器CustomScopeConfigurer-->
    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="threadScop">
                    <!--使用内置的线程类:SimpleThreadScope-->
                    <bean class="org.springframework.context.support.SimpleThreadScope"/>
                </entry>
            </map>
        </property>
    </bean>

    <!--使用上面自动定义的scope-->
    <bean id="springBean" class="com.bjpowernode.spring6.bean.SpringBean" scope="threadScop"/>
</beans>

第四步:执行结果

还是同样的测试代码,可以看出:

对于同一个线程访问的是同一个Bean对象;对于不同的线程访问的是不同的对象!


http://lihuaxi.xjx100.cn/news/957610.html

相关文章

redis启动和关闭服务脚本

编译安装redis&#xff0c;自己写了个脚本。 简单实现启动、关闭和 查看redis服务。 基本流程如下&#xff1a; 脚本执行&#xff0c;必须附带1个参数&#xff0c;没有参数会提示附带参数。 脚本会获取redis-server进程数量。作为开启、关闭以及查看redis服务的数据依据。 …

【自动包装线标签打印翻转问题沟通】

最近纺丝自动包装线的标签打印机自动打印标签&#xff0c;是翻转状态。 但是这个打印机它不是平放的&#xff0c;它是通过悬臂安装在半空的中的&#xff0c;是翻转的&#xff0c; 它的标签一个打在侧面&#xff0c;一个打在正前方&#xff0c;打印出来的样子是这样的。 是反过…

python之异步编程

一、异步编程概述 异步编程是一种并发编程的模式&#xff0c;其关注点是通过调度不同任务之间的执行和等待时间&#xff0c;通过减少处理器的闲置时间来达到减少整个程序的执行时间&#xff1b;异步编程跟同步编程模型最大的不同就是其任务的切换&#xff0c;当遇到一个需要等…

盘点 Vue3 与 Vue2 的区别

一、Vue3 与 Vue2 区别详述 1. 生命周期 对于生命周期来说&#xff0c;整体上变化不大&#xff0c;只是大部分生命周期钩子名称上 “on”&#xff0c;功能上是类似的。不过有一点需要注意&#xff0c;Vue3 在组合式API&#xff08;Composition API&#xff0c;下面展开&…

自动化测试实战篇(8),jmeter并发测试登录接口,模拟从100到1000个用户同时登录测试服务器压力

首先进行使用jmeter进行并发测试之前就需要搞清楚线程和进程的区别还需要理解什么是并发、高并发、并行。还需要理解高并发中的以及老生常谈的&#xff0c;TCP三次握手协议和TCP四次握手协议**TCP三次握手协议指&#xff1a;****TCP四次挥手协议&#xff1a;**进入Jmeter&#…

Qt 防止程序退出

文章目录摘要QWidgetQML方法 1方法 2关键字&#xff1a; Qt、 eventFilter、 Close、 键盘、 任务管理器摘要 今天要聊得内容还是怎么防止别人关闭我的程序&#xff0c;之前都是在win下面&#xff0c;一般都是用过钩子连捕获键盘事件&#xff0c;完了吧对应的事件忽略&#x…

Flutter Button 实例

大家好&#xff0c;我是 17。 在上篇文章 使用 Flutter Button 介绍了如何修改 button 的样式&#xff0c;本文来具体实践一下。 本文列举一些常用的 button 效果&#xff0c;以便在用到的时候方便使用。因为 ElevatedButton 最常用&#xff0c;所以大多以 ElevatedButton 举…

干货 | 提升前端工程化,携程 Design2Code 从零到一的实践

作者简介by&#xff0c;携程高级研发经理&#xff0c;专注低代码平台搭建和前端智能化技术。Jialu&#xff0c;携程研发总监&#xff0c;专注大前端技术和工程化的研究与发展。一、 背景在软件开发过程中&#xff0c;团队协作效率的提高是我们共同关注的问题。为了解决这一问题…