Spirng 当中 Bean的作用域
Spirng 当中 Bean的作用域
@
每博一文案
青年,青年!无论受怎样的挫折和打击,都要咬着牙关挺住,因为你们完全有机会重建生活;只要不灰心丧气,每一次挫折就只不过是通往新境界的一块普通绊脚石,而绝不会置人于死命
_____路遥《平凡的世界》
飞机上邻座的姐姐
独自一人坐飞机去见异地的男友
异地恋赤诚的人好像越来越少
我不自觉地问她
如果以后分手了不会觉得可惜么
她一边低头和男友报备自己落座了
一边回答说“我不是确认了不会分手才去爱他的,我恰恰是因为确定了我们有可能会分手才更要
用力去爱他的,更何况,人是用来拥有的,不是吗”
———————《网友评论》
1. Spring6 当中的 Bean的作用域
1.2 singleton 默认
默认情况下,Spring的IoC容器创建的Bean对象是单例的。
我们来检验一下:
首先,方便大家处理,下面明确出对应相关的 maven配置信息pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rainbowsea</groupId>
<artifactId>spring6-007-circular-dependency</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.11</version>
</dependency>
<!-- junit4 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
对应配置的 bean 的类是 User 这个类 ,为了方便辨析,简单明了,这个 类,就不设置属性了。就是一个空空的类。
package com.rainbowsea.spirngBean;
public class User {
public User() {
System.out.println("User() 的无参数构成方法");
}
}
配置 Spring框架当中的xml 配置文件,让 Spring 知道我们的 User 这个类,并进行管理

<?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 name="user" class="com.rainbowsea.spirngBean.User"></bean>
</beans>
下面编写测试:代码,进行一个测试,验证,Spring 默认是否是 单例的 。这里我们启动多线程,进行一个测试

package com.ranbowsea.test;
import com.rainbowsea.spirngBean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testScope {
@Test
public void test01() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user);
System.out.println(user1);
// 启动线程
new Thread(new Runnable() {
@Override
public void run() {
User user2 = applicationContext.getBean("user", User.class);
User user3 = applicationContext.getBean("user", User.class);
System.out.println(user2);
System.out.println(user3);
}
}).start();
}
}

从结果上看:
- 无参构造方法仅仅只被调用了一次
- 四个user对象,的地址是一样的
说明:无论是执行多少次,
applicationContext.getBean,还是启动多个线程,都是同一个User对象. 是单例的
这个对象在什么时候创建的呢?可以为SpringBean提供一个无参数构造方法,测试一下,如下:

从结果上来看:是在
new ClassPathXmlApplicationContext()的时候就已经,执行了构造方法(Bean对象的创建是在初始化Spring上下文的时候就完成的。)
其中: singleton 是Spring框架 默认的,也是单例的。
我们可以使用:可以在bean标签中指定 scope属性的值为 singleton 。我们测试如下。

<?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 name="user" class="com.rainbowsea.spirngBean.User" scope="singleton"></bean>
</beans>

通过测试得知,没有指定scope属性时,默认是
singleton单例的。
1.3 prototype
如果想让Spring的Bean对象以多例 的形式存在,可以在bean标签中指定 scope属性的值为:prototype,这样Spring会在每一次执行getBean()方法的时候创建Bean对象,调用几次则创建几次。


<?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 name="user" class="com.rainbowsea.spirngBean.User" scope="prototype"></bean>
</beans>
我们来是:用 User 这个类进行测试,使用:


import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testScope {
@Test
public void test() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user);
System.out.println(user1);
}
}
从结果上看:
1.调用了两次无参数构成方法()
2.是两个不同的 user对象的地址
启动多个线程,也是会存在多个,user对象的地址的,同时调用多次无参数构成方法()——> 是多例 的。 不像 singleton(默认)的那样是无论是执行多少次,applicationContext.getBean ,还是启动多个线程,都是同一个User对象单例的。

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testScope {
@Test
public void test() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user);
System.out.println(user1);
// 启动多线程
new Thread(new Runnable() {
@Override
public void run() {
User user2 = applicationContext.getBean("user", User.class);
User user3 = applicationContext.getBean("user", User.class);
System.out.println(user2);
System.out.println(user3);
}
}).start();
}
}
1.4 Spring 中的 bean 标签当中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:很少使用。
特殊说明: 如果大家,进行了一个实践测试代码,可能会发现,IDE工具,仅仅只提示了 scope属性值的两个值(singleton,prototype)。就算我们自己手动敲出了其他的值,也是会报红 。如下图所示:

哈哈哈,这个IDE不给我们提示就算了,还给我们报错。
其实这个并不是IDE工具的问题,而是,我们其他的对应的scope其他属性的值,是需要在特定的情况下才有用的。比如:我们这里的
request是需要在web项目当中才是有用的 ,所以 IDE才给我们来了这么一个错误——》爆红了。
我们可以,在 pom.xml 项目配置文件上,加上一个web 框架,比如:这里我们加上SpringMVC 就可以了。试试

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rainbowsea</groupId>
<artifactId>spring6-007-circular-dependency</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.11</version>
</dependency>
<!-- junit4 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
</dependencies>
</project>

1.5 自定义作用域,一个线程一个 Bean
接下来咱们自定义一个Scope,关于线程级别的Scope,
作用:在同一个线程中,获取的Bean都是同一个。跨线程则是不同的对象。
第一步:自定义Scope。(实现Scope接口)
spring内置了线程范围的类:
org.springframework.beans.factory.config.CustomScopeConfigurer,和org.springframework.context.support.SimpleThreadScope可以直接用。
- 第二步:将自定义的Scope注册到Spring容器中。

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="myThread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
<?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">
<!-- 自定义一个 scope属性值:作用:在同一个线程中,获取的Bean都是同一个。跨线程则是不同的对象。-->
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes"> <!-- set 注入,为该类当中的 name 属性赋值-->
<map> <!-- map集合 注入,为该类当中的 key 属性赋值,也就是我们自定义的 scope的属性值的名字-->
<entry key="myThread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
<bean name="user" class="com.rainbowsea.spirngBean.User" scope="myThread"></bean>
</beans>
我们还是使用 User 这个类,作为 Bean 进行一个测试。

启动多个线程,处理。

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class testScope {
@Test
public void test() {
// 第一个线程
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user);
System.out.println(user1);
// 启动多线程
// 第二个线程
new Thread(new Runnable() {
@Override
public void run() {
User user2 = applicationContext.getBean("user", User.class);
User user3 = applicationContext.getBean("user", User.class);
System.out.println(user2);
System.out.println(user3);
}
}).start();
}
}
从结果上,我们可以看出:
一个线程,调用了一次无参构造方法(),生产一个对象。
成功实现了。在同一个线程中,获取的Bean都是同一个。跨线程则是不同的对象。
2. 总结:
- 默认情况下,Spring的IoC容器创建的Bean对象是单例的。默认是singleton(单例的)
- 可以在bean标签中指定scope属性的值为:**prototype(多例),默认是singleton(单例的) **
- 同时要注意:scope属性的值不止两个,它一共包括8个选项:,其他的要在特定的配置下,才能使用,例如:request和session 要是在
web框架才可以使用。
3. 最后:
“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”
Spirng 当中 Bean的作用域的更多相关文章
- Spring -- Bean自己主动装配&Bean之间关系&Bean的作用域
对于学习spring有帮助的站点:http://jinnianshilongnian.iteye.com/blog/1482071 Bean的自己主动装配 Spring IOC 容器能够自己主动装配 ...
- (五)SpringIoc之Bean的作用域
此文转自 https://blog.csdn.net/icarus_wang/article/details/51586776# 有状态bean和无状态bean请看 https://blog.csdn ...
- Spring核心技术(五)——Spring中Bean的作用域
前文概述了Spring的容器,Bean,以及依赖的一些信息,本文将描述一下Bean的作用域 Bean的作用域 当开发者定义Bean的时候,同时也会定义了该如何创建Bean实例.这些具体创建的过程是很重 ...
- Spring(Ioc和Bean的作用域)
Spring Spring为简化开发而生,让程序员只关心核心业务的实现,尽可能的不在关注非业务逻辑代码(事务控制,安全日志等). 1,Spring八大模块 这八大模块组成了Spring 1.1 Spr ...
- Spring中Bean的作用域、生命周期
Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ...
- Spring bean的作用域和生命周期
bean的作用域 1.singleton,prototype, web环境下:request,session,gloab session 2.通过scope="" 来进行配置 3. ...
- Bean 的作用域
•在 Spring 中, 可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域. 默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一一个实 ...
- [原创]java WEB学习笔记99:Spring学习---Spring Bean配置:自动装配,配置bean之间的关系(继承/依赖),bean的作用域(singleton,prototype,web环境作用域),使用外部属性文件
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Bean的作用域及生命周期
指定bean的作用域通过scope属性 singleton单实例模式,从初始化容器就初始化bean,除非延迟初始化lazy-init=true prototype每次从容器获取bean是新的对象,从g ...
- Spring基础—— Bean 的作用域
一.在 Spring Config 文件中,在 <bean> 元素的 scope 属性里设置 Bean 的作用域.默认为 singleton ,单例的. 二.在不引入 spring-web ...
随机推荐
- 分享一个项目:go `file_line`,在编译器得到源码行号,减少运行期runtime消耗
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 file_line https://github.com/ ...
- 在使用若依分离版时遇到富文本不显示html解决
<el-table-column label="公告内容" align="center" prop="content"> < ...
- DRConv:旷视提出区域感知动态卷积,多任务性能提升 | CVPR 2020
论文提出DRConv,很好地结合了局部共享的思想并且保持平移不变性,包含两个关键结构,从实验结果来看,DRConv符合设计的预期,在多个任务上都有不错的性能提升 来源:晓飞的算法工程笔记 公众号 ...
- KingbaseES 优化之sql优化方法
金仓数据库在sql层面提供了多种优化手段,但是这些的前提时需要保证我们的统计信息准确,优化器已经在正确信息下选择了它认为的最优的执行计划, 优化手段包括 •使用索引 索引解决的问题用于在进行表的扫描时 ...
- KingbaseES V8R6集群部署案例之---openEuler系统脚本部署故障
案例说明: 在openEuler系统下通过脚本方式部署KingbaseES V8R6集群,脚本执行过程中,加载vip失败.本次故障问题,主要是因为openEuler系统shell和脚本的不兼容引起. ...
- archlinux xfce未中文化 goldendict不能显示中文
下载个中文字体包就好了 https://wiki.archlinuxcn.org/wiki/简体中文本地化
- Scala 函数闭包和柯里化
1 package com.atguigu.function 2 3 object HighFunction { 4 def main(args: Array[String]): Unit = { 5 ...
- 做好PPT,提高沟通效率
本文于2019年7月12日完成,发布在个人博客网站上. 考虑个人博客因某种原因无法修复,于是在博客园安家,之前发布的文章逐步搬迁过来. 只用一套PPT来通杀全部使用场景,这个想法其实很天真. 作为一种 ...
- 深入理解 Java 循环结构:while、do while、for 和 for-each 循环
Java 循环 循环可以执行一个代码块,只要达到指定的条件.循环很方便,因为它们节省时间,减少错误,并使代码更易读. Java While 循环 while 循环会循环执行一个代码块,只要指定的条件为 ...
- SQL 中的 MIN 和 MAX 以及常见函数详解及示例演示
SQL MIN() 和 MAX() 函数 SQL中的MIN()函数和MAX()函数用于查找所选列的最小值和最大值,分别.以下是它们的用法和示例: MIN() 函数 MIN()函数返回所选列的最小值. ...

