Spring学习记录之Bean的作用域
Spring学习记录之Bean的作用域
前言
这篇文章是我第二次学习b站老杜的spring
相关课程所进行的学习记录
,算是对课程内容及笔记的二次整理,以自己的理解方式进行二次记录,其中理解可能存在错误,欢迎且接受各位大佬们的批评指正;
关于本笔记,只是我对于相关知识遗忘时快速查阅了解使用,至于课程中实际实验配置等,也只是记录关键,并不会记录详细步骤,若想了解可以关注我博客的项目经验模块,我会在实际项目开发过程中总结项目经验,在该模块发布!
学习视频地址:https://www.bilibili.com/video/BV1Ft4y1g7Fb/
视频配套笔记:https://www.yuque.com/dujubin/ltckqu/kipzgd?singleDoc# 《Spring6》 密码:mg9b
目录
一、我个人对这部分学习的一些见解
这部分主要讲述Spring
管理的Bean
的作用域,即Bean
在Spring
容器中是单例还是多例等;以及如何自定义Bean
的作用域。这部分是需要重点了解的内容,学习完Spring
后要有Bean
作用域的概念。
这部分我会继续引用老杜的笔记。
二、Bean的作用域
① singleton(单例)
默认情况下,Spring的IoC容器创建的Bean对象是单例的。来测试一下:
SpringBean
package com.powernode.spring6.beans;
/**
* @author 动力节点
* @version 1.0
* @className SpringBean
* @since 1.0
**/
public class SpringBean {
}
spring-scope.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="sb" class="com.powernode.spring6.beans.SpringBean" />
</beans>
测试程序:
@Test
public void testScope(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");
SpringBean sb1 = applicationContext.getBean("sb", SpringBean.class);
System.out.println(sb1);
SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class);
System.out.println(sb2);
}
执行结果:
通过测试得知:Spring的IoC容器中,默认情况下,Bean对象是单例的。
这个对象在什么时候创建的呢?可以为SpringBean
提供一个无参数构造方法,测试一下,如下:
SpringBean
package com.powernode.spring6.beans;
/**
* @author 动力节点
* @version 1.0
* @className SpringBean
* @since 1.0
**/
public class SpringBean {
public SpringBean() {
System.out.println("SpringBean的无参数构造方法执行。");
}
}
将测试程序中getBean()
所在行代码注释掉:
测试程序:
@Test
public void testScope(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");
}
执行测试程序:
通过测试得知,默认情况下,Bean对象的创建是在初始化Spring上下文的时候就完成的。
② prototype(多例)
如果想让Spring
的Bean
对象以多例的形式存在,可以在bean
标签中指定scope
属性的值为:prototype
,这样Spring
会在每一次执行getBean()
方法的时候创建Bean
对象,调用几次则创建几次。(默认单例只在容器初始化的时候创建一次被管理的Bean
对象)
spring-scope.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="sb" class="com.powernode.spring6.beans.SpringBean" scope="prototype" />
</beans>
测试程序:
@Test
public void testScope(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");
SpringBean sb1 = applicationContext.getBean("sb", SpringBean.class);
System.out.println(sb1);
SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class);
System.out.println(sb2);
}
执行结果:
我们可以把测试代码中的getBean()
方法所在行代码注释掉:
测试代码:
@Test
public void testScope(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");
}
执行结果:
可以看到这一次在初始化Spring
上下文的时候,并没有创建Bean
对象。
那你可能会问:scope
如果没有配置,它的默认值是什么呢?默认值是singleton
,单例的。
spring-scope.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="sb" class="com.powernode.spring6.beans.SpringBean" scope="singleton" />
</beans>
测试程序:
@Test
public void testScope(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");
SpringBean sb1 = applicationContext.getBean("sb", SpringBean.class);
System.out.println(sb1);
SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class);
System.out.println(sb2);
}
执行结果:
通过测试得知,没有指定scope属性时,默认是singleton单例的。
三、其它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
:很少使用。
接下来咱们自定义一个Scope
,线程级别的Scope
,在同一个线程中,获取的Bean
都是同一个。跨线程则是不同的对象:(以下内容作为了解)
-
第一步:自定义
Scope
。(实现Scope
接口) -
spring
内置了线程范围的类:org.springframework.context.support.SimpleThreadScope
,可以直接用。
-
第二步:将自定义的
Scope
注册到Spring
容器中。spring-scope.xml
<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>
-
第三步:使用Scope。
spring-scope.xml
<bean id="sb" class="com.powernode.spring6.beans.SpringBean" scope="myThread" />
编写测试程序:
@Test public void testCustomScope(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml"); SpringBean sb1 = applicationContext.getBean("sb", SpringBean.class); SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class); System.out.println(sb1); System.out.println(sb2); // 启动线程 new Thread(new Runnable() { @Override public void run() { SpringBean a = applicationContext.getBean("sb", SpringBean.class); SpringBean b = applicationContext.getBean("sb", SpringBean.class); System.out.println(a); System.out.println(b); } }).start(); }
执行结果:
四、总结
这部分我们了解到:
Spring
的IoC
容器中,默认情况下,Bean对象是单例的!- 默认情况下,
Spring
中Bean
对象的创建是在初始化Spring
上下文的时候就完成的。 scope
属性的值不止两个,它一共包括8个选项。均在特定的情况下使用。- 如果框架提供的作用域不符合要求,还可以自定义
Bean
的作用域。
这里需要去了解老杜这节相关讲解,可以直接点击下面链接跳转到对应课程学习了解!