本文内容

  1. bean定义信息的意义
  2. 介绍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();
} }

如何使用?

  1. 先将自定义的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>
  2. 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的作用域的更多相关文章

  1. (转)配置Spring管理的bean的作用域

    http://blog.csdn.net/yerenyuan_pku/article/details/52833477 Spring管理的bean的作用域有: singleton 在每个Spring ...

  2. Spring基础11——Bean的作用域

    1.Bean的作用域种类 Spring中的bean的作用域分为四种:singleton.prototype.session.request,后两种很少使用,下面我们主要来学习前两种 2.singlet ...

  3. Spring框架系列(三)--Bean的作用域和生命周期

    Bean的作用域 Spring应用中,对象实例都是在Container中,负责创建.装配.配置和管理生命周期(new到finalize()) Spring Container分为两种: 1.BeanF ...

  4. Spring系列之bean的使用

    一.Bean的定义 <bean id="userDao" class="com.dev.spring.simple.MemoryUserDao"/> ...

  5. Spring 学习笔记 Bean的作用域

    在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域.作用域将对Bean的生命周期和创建方式产生影响.在低版本的Spring中,仅有两个作用域 ...

  6. Spring系列(三) Bean装配的高级技术

    profile 不同于maven的profile, spring的profile不需要重新打包, 同一个版本的包文件可以部署在不同环境的服务器上, 只需要激活对应的profile就可以切换到对应的环境 ...

  7. Spring系列(二) Bean装配

    创建应用对象之间协作关系的行为称为装配(wiring), 这也是DI的本质. Spring中装配Bean的方式 Spring提供了三种装配Bean的方式. 隐式的Bean发现机制和自动装配 Java ...

  8. Spring第五弹—–配置Spring管理的bean的作用域和生命周期

    singleton (默认方式) 在每个Spring IoC容器中一个bean定义只有一个对象实例.默认情况下会在容器启动时初始化bean,但我们可以指定bean节点的lazy-init=“true” ...

  9. (三)Spring 高级装配 bean的作用域@Scope

    1.默认情况下,spring通过@Autowared注入的bean是单例的bean,但有些情况是不满足的,例如:购物车,每个会话,或每个用户登录使用的购物车都是独立的 spring的定义的作用域: a ...

  10. 配置spring管理的bean的作用域

    .singleton 在每一个spring Ioc容器中一个bean定义只有一个对象实例.默认情况下会在容器启动时初始化bean,但我们可以指定bean节点的lazy-init = "tru ...

随机推荐

  1. 【LeetCode】655. Print Binary Tree 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS BFS 日期 题目地址:https://le ...

  2. Cornfields(poj2019)

    Cornfields Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6798   Accepted: 3315 Descri ...

  3. codeforce-600C. Make Palindrome(贪心)

    http://codeforces.com/problemset/problem/600/C: 题意:给你一个小写字母组成的英文串,将它转换为回文串,要求,改变的字母的个数最小,移动字母不算改变字母. ...

  4. 1017 - Brush (III)

    1017 - Brush (III)   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Sami ...

  5. Spring MVC 文件上传、Restful、表单校验框架

    目录 文件上传 Restful Restful 简介 Rest 行为常用约定方式 Restful开发入门 表单校验框架 表单校验框架介绍 快速入门 多规则校验 嵌套校验 分组校验 综合案例 实用校验范 ...

  6. ROC and AUC

    目录 概 TPR, FPR ROC and AUC 代码 ROC-wiki 概 AUC常常在文章中作为评价一个分类器优劣的指标, 却总是忘记其原由, 索性记上一笔. TPR, FPR 首先理解TP, ...

  7. <数据结构>图的最短路径问题

    目录 最短路径问题 Dijstra算法:中介点优化 基本步骤 伪代码 在实现过程中的关键问题 代码实现 邻接矩阵版 邻接表版 时间复杂度:O(VlogV+E) 算法存在的问题:存在负权边时会失效 Be ...

  8. ProtoBuf3语法指南(Protocol Buffers)_下

    0.说明 ProtoBuf3语法指南, 又称为proto3, 是谷歌的Protocol Buffers第3个版本. 本文基于官方英文版本翻译, 加上了自己的理解少量修改, 一共分为上下两部分. 1.A ...

  9. SSH公/私秘钥的生成及使用

    如果使用GitHub比较多的朋友,对SSH Key肯定也不陌生,当我们SSH进行代码的pull&push时,往往需要我们配置SSH Key. 如果Linux用的多朋友,肯定对SSH Key都很 ...

  10. mysql在Linux下大小写敏感设置

    默认情况下,mysql在windows下是不区分大小写的,但是mysql在linux下大小写规则是这样的: 1.数据库名与表名是严格区分大小写的: 2.表的别名是严格区分大小写的: 3.列名与列的别名 ...