10.7 自定义Scope

如果用户觉得Spring内置的几种Scope不能满足需求,则可以定制自己的Scope,即实现自己的org.springframework.beans.factory.config.Scope。Scope接口定义了如下几个方法,详情请参看Spring的API文档。

public interface Scope {Object get(String name, ObjectFactory<?> objectFactory);Object remove(String name);void registerDestructionCallback(String name, Runnable callback);Object resolveContextualObject(String key);String getConversationId();}

下面来看一下Spring内部Scope为application的定义,即ServletContextScope的定义。

public class ServletContextScope implements Scope, DisposableBean {private final ServletContext servletContext;private final Map<String, Runnable> destructionCallbacks = new LinkedHashMap<String, Runnable>();/**
     * Create a new Scope wrapper for the given ServletContext.
     * @param servletContext the ServletContext to wrap
     */public ServletContextScope(ServletContext servletContext) {Assert.notNull(servletContext, "ServletContext must not be null");this.servletContext = servletContext;}@Overridepublic Object get(String name, ObjectFactory<?> objectFactory) {Object scopedObject = this.servletContext.getAttribute(name);if (scopedObject == null) {scopedObject = objectFactory.getObject();this.servletContext.setAttribute(name, scopedObject);}return scopedObject;}@Overridepublic Object remove(String name) {Object scopedObject = this.servletContext.getAttribute(name);if (scopedObject != null) {this.servletContext.removeAttribute(name);this.destructionCallbacks.remove(name);return scopedObject;}else {return null;}}@Overridepublic void registerDestructionCallback(String name, Runnable callback) {this.destructionCallbacks.put(name, callback);}@Overridepublic Object resolveContextualObject(String key) {return null;}@Overridepublic String getConversationId() {return null;}/**
     * Invoke all registered destruction callbacks.
     * To be called on ServletContext shutdown.
     * @see org.springframework.web.context.ContextCleanupListener
     */@Overridepublic void destroy() {for (Runnable runnable : this.destructionCallbacks.values()) {runnable.run();}this.destructionCallbacks.clear();}}

10.7.1 注册

自定义了Scope之后我们得在Spring中进行注册,好让Spring能够对其进行识别,这样我们才能在进行对应bean定义的时候使用自定义的Scope。自定义Scope的注册有两种方式,一种是程序化的,一种是通过XML进行配置的。
我们先来实现一个自定义的Scope供注册自定义Scope使用。

public class MyScope implements Scope {private Map<String, Object> beanMap = new ConcurrentHashMap<String, Object>();/**
     * 获取指定beanName的bean实例
     * @param name 对应bean的beanName
     * @param objectFactory 可以产生对应bean实例的ObjectFactory
     * @return 获取到的实例
     */public Object get(String name, ObjectFactory<?> objectFactory) {System.out.println("------------get-----------" + name);synchronized (this) {if (!beanMap.containsKey(name)) {System.out.println("-----------not--exists-------" + name);beanMap.put(name, objectFactory.getObject());}}return beanMap.get(name);}/**
     * 底层移除name对应的对象。实现者需要同时移除注册的销毁化回调方法
     * @param name
     * @return 移除的对象
     */public Object remove(String name) {return beanMap.remove(name);}/**
     * 注册一个销毁时的回调方法
     * @param name
     * @param callback
     */public void registerDestructionCallback(String name, Runnable callback) {}public Object resolveContextualObject(String key) {return null;}public String getConversationId() {return null;}}

程序化注册自定义Scope是通过ConfigurableBeanFactory的registerScope()方法进行的,其对应定义如下,scopeName表示我们需要注册的scope的名称,第二个参数Scope表示我们需要注册的Scope的一个实例。

  /**
     * Register the given scope, backed by the given Scope implementation.
     * @param scopeName the scope identifier
     * @param scope the backing Scope implementation
     */void registerScope(String scopeName, Scope scope);

我们可以通过常用的ApplicationContext,如ClassPathXmlApplicationContext等的getBeanFactory()方法就能获取到对应的ConfigurableBeanFactory对象,然后进行注册。如:

   ClassPathXmlApplicationContext context = ...;context.getBeanFactory().registerScope("myScope", new MyScope());

通过XML配置进行注册是指通过在Spring的配置文件中定义一个CustomScopeConfigurer类型的bean,并通过其setScopes()方法注入自定义Scope。如下所示,我们通过XML配置注册了一个名叫myScope的Scope定义。

  <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"><property name="scopes"><map><entry key="myScope"><bean class="com.app.MyScope"/></entry></map></property></bean>

之后就可以在定义bean的时候使用我们自己定义的myScope来作为bean定义的Scope了。

   <bean id="hello" class="com.app.Hello" scope="myScope"/>

在上述配置中我们指定了id为hello的bean定义的scope为自定义的myScope。之后运行如下测试代码,我们可以看到控制台的输出过程。我们每从bean容器中获取一次hello的实例,对应MyScope的get()方法就会被调用一次。

  @org.junit.Testpublic void test() {System.out.println(context.getBean("hello"));System.out.println(context.getBean("hello"));}

(注:本文是基于Spring4.1.0所写)

Spring(10)——bean作用范围(二)—自定义scope相关推荐

  1. 【Spring】bean的作用域(@Scope) - singleton、prototype

    已知spring 3+已拥有多种不同的作用域: singleton(默认).prototype.request.session.global session.(参考: spring中scope作用域( ...

  2. 【spring】Bean的Scope与自定义Scope

    Bean的作用域 在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为Bean.简单地讲,bean就是由IoC容器初始化.装配及管理的对象,除此之外,bean就与 ...

  3. 标签系列二:spring 中bean解释以及bean标签里面的属性

    一.bean标签: 英文解释:Defines a single (usually named) bean. A bean definition may contain nested tags for ...

  4. java spring scope_如何在Spring中自定义scope的方法示例

    大家对于 Spring 的 scope 应该都不会默认.所谓 scope,字面理解就是"作用域"."范围",如果一个 bean 的 scope 配置为 sing ...

  5. error:lnk2005 已经在*.obj中定义_如何在 Spring 中自定义 scope

    大家对于 Spring 的 scope 应该都不会默认.所谓 scope,字面理解就是"作用域"."范围",如果一个 bean 的 scope 配置为 sing ...

  6. 如何在 Spring 中自定义 scope

    大家对于 Spring 的 scope 应该都不会默认.所谓 scope,字面理解就是"作用域"."范围",如果一个 bean 的 scope 配置为 sing ...

  7. 【Spring】Spring 自定义scope

    1.概述 有时候,spring内置的几种sope都无法满足我们的需求的时候,我们可以自定义bean的作用域. 1.1 自定义Scope 3步骤 1.1.1 第1步:实现Scope接口 我们来看一下这个 ...

  8. Spring源码系列(十二)Spring创建Bean的过程(二)

    1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...

  9. spring中Bean的作用范围

    Spring中Bean的作用范围 Singleton:使用该属性定义Bean时,IOC容器仅创建一个Bean实例,IOC容器每次返回的是同一个Bean实例. singleton是默认的作用域,当定义B ...

最新文章

  1. 怎样在swift中创建CocoaPods
  2. java 算法--洗牌算法
  3. 用MS SQL 语句修改表中字段类型
  4. Docker进阶-快速扩容
  5. 建造者模式源码解析(jdk-guava+mybatis)
  6. jdbc-------JDBCUtil类 工具类
  7. java 8是指什么_java中8个基本数据类型到底是指什么?是什么意思,有什么作用?我需要权威的回答,...
  8. java/javascript 时间操作工具类
  9. Python-Flask构建微信小程序订餐系统-Flask打造高可用flask mvc框架-08
  10. 职场精英修炼必学工具:75页自我管理的29个工具,系统方法论
  11. java break 在if 中使用_Java | 使用JNA在Java中实现cls(cmd清屏)功能
  12. 老李分享:Web Services 组件
  13. 百度云 java私塾_JAVA私塾-百度云
  14. 安全基础教育第二季第1集:屡战屡败的找回密码
  15. 32单片机——pwm波输出
  16. windows10没有nfs服务_3GB+极度精简+不更新,被誉为最纯净Windows10,老爷机总算有救了...
  17. 蜂鸣器音乐代码 天空之城_歌单 | 音乐拥有魔力
  18. moment格式化时间
  19. CHAPTER 2 Docker镜像
  20. php 数字上下选取,PHP中常见的数字掐头去尾操作方法

热门文章

  1. cupsd进程_linux pstree命令显示正在运行的进程的进程树状图
  2. mac os 编译android,Mac OS X 编译Android内核源代码
  3. json解析对应的value为null_解决golang json解析出现值为空的问题
  4. python优先队列使用_Python优先队列实现方法示例
  5. c语言如何将一个二维数组全为零_从零开始如何用python处理数据
  6. 我的世界pc正版好玩的服务器,都来看看好玩的服务器
  7. matlab分析电池特性,基于Matlab_Simulink的光伏电池特性仿真研究
  8. jwt 私钥_三分钟带你了解JWT认证
  9. SpringSecurity Filter顺序
  10. Java proxy 子类代理