本文内容

  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. AWS 15 年(1):从 Serverful 到 Serverless

    2006年,AWS发布了其第一个Serverless存储服务S3和第一个Serverful计算服务EC2,这也是AWS正式发布的前两个服务,开启了云计算波澜壮阔的旅程.2014年,AWS发布了业界第一 ...

  2. Python 英语单词本

    python pymysql re requests socket库的简单运用 要考试了,这里用所学的知识做一个实例 pymysql库 这个库是用来连接数据库的,使用数据库语句在python里创建表和 ...

  3. 【C++】leetcode竞赛笔记

    *注--代码非博主本人所写,仅供学习参考,侵删 20200516双周赛: 1 to_string(int a) 将a转换成字符串形式 2 gcd(int a,int  b) 返回a,b的最大公约数,若 ...

  4. 第九个知识点:香农(Shannon)定义的熵和信息是什么?

    第九个知识点:香农(Shannon)定义的熵和信息是什么 这是计算机理论的最后一篇.我们讨论信息理论的基础概念,什么是香农定义的熵和信息. 信息论在1948年被Claude E.Shannon建立.信 ...

  5. matplotlib 进阶之Tight Layout guide

    目录 简单的例子 Use with GridSpec Legend and Annotations Use with AxesGrid1 Colorbar 函数链接 matplotlib教程学习笔记 ...

  6. 单芯片CS5265替代VL102+PS176|设计USB TYPEC转HDMI方案|替代VL102+PS176

    一.PS176概述PS176是一个显示端口 (DP)至HDMI 2.0视频接口转换器适用于需要视频协议转换的电缆适配器.电视接收器.监视器和其他应用.它将接受任何显示端口输入格式,包括DP 1.1a. ...

  7. 编写Java程序_定义两个方法,实现奇数偶数的判断,并计算和(有参数有返回值方法)

    需求说明: 定义两个方法,在控制台输入一个数字,这两个方法可以求出1到该数字之间所有偶数之和.奇数之和,并将对应结果和返回.在main方法中调用该方法,并在控制台打印出结果.(有参数有返回值方法) 运 ...

  8. Browser Events 常用浏览器事件

    事件 说明 click 鼠标点击时触发此事件 dblclick 鼠标双击时触发此事件 mousedown 按下鼠标时触发此事件 mouseup 鼠标按下后松开鼠标时触发此事件 mouseover 当鼠 ...

  9. MongoDB与微服务

    1. 微服务的优势 * 开发速度快 * 变化响应快 * 易维护 * 扩容简单2. 微服务架构设计要素 * 服务解耦(Decouple) * HTTP API - 简单接口(Dumb Pipes) * ...

  10. 适配器模式(pthon)

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- # adapter_pattern.py # 适配器模式 class Adaptee: def reque ...