Spring系列8:bean的作用域
本文内容
- bean定义信息的意义
- 介绍6种bean的作用域
bean定义信息的意义
Spring中区分下类、类定义信息,类实例对象的概念?不容易理解,以餐馆中点炒饭为例。
类: 相当于你看到菜单上炒饭这个菜品,有这个菜。
类定义信息:相当于炒饭的烹饪法,烹饪法只有一份
类实例对象: 相当于按照上面烹饪法炒出来的一份炒饭,可以炒分多份出来。
Spring容器中创建了一个类定义信息的,就可以根据这个定义信息来创建个类实例对象出来,这个理解了很关键。Spring中不仅可以控制 bean 对象中的各种依赖项和配置值,还可以控制 bean 额作用范围。
介绍6种bean的作用域
Spring Framework 支持6个bean的作用域,其中4个仅在web类型的 ApplicationContext 中可用。详细见下表
| 作用域 | 描述 |
|---|---|
| singleton | (默认)将单个 bean 定义限定为每个 Spring IoC 容器的单个对象实例。 |
| prototype | 将单个 bean 定义限定为任意数量的对象实例 |
| request | 将单个 bean 定义限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有自己的 bean 实例,该实例是在单个 bean 定义的后面创建的。仅在web类型的 ApplicationContext有效。 |
| session | 将单个 bean 定义限定为 HTTP 会话的生命周期。仅在web类型的 ApplicationContext有效。 |
| application | 将单个 bean 定义限定为 ServletContext 的生命周期。仅在web类型的 ApplicationContext有效。 |
| websocket | 将单个 bean 定义限定为 WebSocket 的生命周期。仅在web类型的 ApplicationContext有效。 |
从 Spring 3.0 开始,线程范围可用,但默认情况下未注册。
SimpleThreadScope感兴趣可以详细看下面自定义作用域。
singleton
只有一个单例 bean 的共享实例被管理,并且所有对具有与该 bean 定义匹配的一个或多个 ID 的 bean 的请求都会导致 Spring 容器返回一个特定的 bean 实例。"蝎子粑粑独一份"。注意是一个IoC容器内。

prototype
原型作用域下每次容器都会创建一个新的 bean 实例。通常来说,对有状态 bean适合使用原型,对无状态 bean适合使用单例。
下面的配置节指定了bean的作用域是原型的。
<bean id="accountService" class="x.y.z.AccountService" scope="prototype"/>
与其他范围相比,Spring 不管理原型 bean 的完整生命周期。容器实例化、配置和以其他方式组装原型对象并将其传递给客户端,由客户端去管理。bean生命周期后面介绍。
request, session, application, webSocket
这4个在web的应用上下文中使用的作用域,暂不展开讲,留给后面写spring mvc 专门讲。
自定义作用域和使用
如何自定义?
可以通过实现org.springframework.beans.factory.config.Scope自定义作用域。Scope 接口有四种方法可以从作用域中获取对象,将它们从作用域中移除,并让它们被销毁。
package org.springframework.beans.factory.config;
public interface Scope {
// 从底层范围返回具有给定名称的对象
Object get(String name, ObjectFactory<?> objectFactory);
// 从底层范围中删除具有给定的对象
Object remove(String name);
// 注册要在作用域中指定对象的销毁时执行的回调
void registerDestructionCallback(String name, Runnable callback);
// 省略
}
打铁要趁热,直接上SimpleThreadScope的源码,解析下线程级别作用域是如何实现的。
package org.springframework.context.support;
public class SimpleThreadScope implements Scope {
private static final Log logger = LogFactory.getLog(SimpleThreadScope.class);
// 1 bean是存放在ThreadLocal中的 绑定了当前线程
private final ThreadLocal<Map<String, Object>> threadScope =
new NamedThreadLocal<Map<String, Object>>("SimpleThreadScope") {
@Override
protected Map<String, Object> initialValue() {
return new HashMap<>();
}
};
// 2 查ThreadLocal,有对应bean就直接返回,没有就创建一个放入ThreadLocal,在返回
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> scope = this.threadScope.get();
Object scopedObject = scope.get(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
scope.put(name, scopedObject);
}
return scopedObject;
}
// 3 从ThreadLocal中移除bean
@Override
@Nullable
public Object remove(String name) {
Map<String, Object> scope = this.threadScope.get();
return scope.remove(name);
}
// 4 销毁回调
@Override
public void registerDestructionCallback(String name, Runnable callback) {
logger.warn("SimpleThreadScope does not support destruction callbacks. " +
"Consider using RequestScope in a web environment.");
}
@Override
@Nullable
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return Thread.currentThread().getName();
}
}
如何使用?
先将自定义的scope注入到容器中
编码的方式注册:
ConfigurableBeanFactory接口提供了registerScope来注册自定义的scope。Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);
配置文件方式的注册: 使用
CustomScopeConfigurer以声明方式进行注册<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
</beans>
bean配置中使用
使用方式普通的scope一样。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean> <bean id="thing2" class="x.y.Thing2" scope="thread">
<property name="name" value="Rick"/>
<aop:scoped-proxy/>
</bean> <bean id="thing1" class="x.y.Thing1">
<property name="thing2" ref="thing2"/>
</bean> </beans>
总结
本文Spring中的7种作用域,以及如何自定义作用域并使用。下一篇介绍基于注解的Spring容器配置。
知识分享,转载请注明出处。学无先后,达者为先!
Spring系列8:bean的作用域的更多相关文章
- (转)配置Spring管理的bean的作用域
http://blog.csdn.net/yerenyuan_pku/article/details/52833477 Spring管理的bean的作用域有: singleton 在每个Spring ...
- Spring基础11——Bean的作用域
1.Bean的作用域种类 Spring中的bean的作用域分为四种:singleton.prototype.session.request,后两种很少使用,下面我们主要来学习前两种 2.singlet ...
- Spring框架系列(三)--Bean的作用域和生命周期
Bean的作用域 Spring应用中,对象实例都是在Container中,负责创建.装配.配置和管理生命周期(new到finalize()) Spring Container分为两种: 1.BeanF ...
- Spring系列之bean的使用
一.Bean的定义 <bean id="userDao" class="com.dev.spring.simple.MemoryUserDao"/> ...
- Spring 学习笔记 Bean的作用域
在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域.作用域将对Bean的生命周期和创建方式产生影响.在低版本的Spring中,仅有两个作用域 ...
- Spring系列(三) Bean装配的高级技术
profile 不同于maven的profile, spring的profile不需要重新打包, 同一个版本的包文件可以部署在不同环境的服务器上, 只需要激活对应的profile就可以切换到对应的环境 ...
- Spring系列(二) Bean装配
创建应用对象之间协作关系的行为称为装配(wiring), 这也是DI的本质. Spring中装配Bean的方式 Spring提供了三种装配Bean的方式. 隐式的Bean发现机制和自动装配 Java ...
- Spring第五弹—–配置Spring管理的bean的作用域和生命周期
singleton (默认方式) 在每个Spring IoC容器中一个bean定义只有一个对象实例.默认情况下会在容器启动时初始化bean,但我们可以指定bean节点的lazy-init=“true” ...
- (三)Spring 高级装配 bean的作用域@Scope
1.默认情况下,spring通过@Autowared注入的bean是单例的bean,但有些情况是不满足的,例如:购物车,每个会话,或每个用户登录使用的购物车都是独立的 spring的定义的作用域: a ...
- 配置spring管理的bean的作用域
.singleton 在每一个spring Ioc容器中一个bean定义只有一个对象实例.默认情况下会在容器启动时初始化bean,但我们可以指定bean节点的lazy-init = "tru ...
随机推荐
- 【LeetCode】684. Redundant Connection 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 并查集 日期 题目地址:https://leetco ...
- 深入理解Java虚拟机二:垃圾收集与内存分配
垃圾收集:垃圾收集要完成三件事,包括哪些内存需要回收,什么时候回收及如何回收. 1.需要回收的内存判定:没有引用指向原先分配给某个对象的内存时,则该内存是需要回收的垃圾 Java垃圾收集器在对内存进行 ...
- 加深理解Java异常概念并熟记5个最常见的运行时异常
加深理解Java异常概念并熟记5个最常见的运行时异常 说明Error与Exception的联系和区别有哪些? 列举最常见的5个运用时异常. 1.Error和Exception的联系和区别: Error ...
- jsp:useBean的scope属性
目录 1.分类 2.page 3.request 4.session 5.application 1.分类 对于jsp:useBean创建的对象,由jsp:useBean的可选属性scope指定,可以 ...
- Python原生数据结构增强模块collections
collections简介 python提供了4种基本的数据结构:list.tuple.dict.set.基本数据结构完全可以hold住所有的场景,但是在处理数据结构复杂的场景时,这4种数据结构有时会 ...
- Spring @Component 注解的使用
使用说明 这个注解用于声明当前的类是一个组件类,Spring 会通过类路径扫描来自动侦测和自动装配这些组件,创建一个个 bean 后,注册到 Spring 容器中. 带 @Component 注解的类 ...
- Selenium_使用switch_to.frame处理网页框架切换(13)
与在新窗口打开一个网页后需要切换窗口才能定位元素一样,在iframe标签中的元素也不能直接定位,需要切换到对应的iframe框架中才能进行元素定位. 完成网页框架切换操作需要用selenium中的两个 ...
- spring boot + spring security +前后端分离【跨域】配置 + ajax的json传输数据
1.前言 网上各个社区的博客参差不齐 ,给初学者很大的困扰 , 我琢磨了一天一夜,到各个社区找资料,然后不断测试,遇到各种坑,一言难尽啊,要么源码只有一部分,要么直接报错... 最后实在不行,直接去看 ...
- 实验 1 :Mininet 源码安装和可视化拓扑
实验 1 : Mininet 源码安装和可视化拓扑工具 一 .实验目的 掌握 Mininet 的源码安装方法和 miniedit 可视化拓扑生成工具. 二 .实验任务 使用源码安装 Mininet 的 ...
- Echart可视化学习(九)
文档的源代码地址,需要的下载就可以了(访问密码:7567) https://url56.ctfile.com/f/34653256-527823386-04154f 官网找到类似实例, 适当分析,并且 ...