Spring(10)——bean作用范围(二)——自定义scope

来源:互联网 发布:ubuntu安装桌面环境 编辑:程序博客网 时间:2024/06/05 01:07

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所写)

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 2岁半宝宝说什么不听话怎么办? 误把脱毛膏当牙膏用了刷牙怎么办 儿子1岁5个月了不说话怎么办 两岁小儿不会说话和智商低怎么办 宝宝不会说话教他说他不愿意怎么办 25个月宝宝不愿意学说话怎么办 老师说小孩在幼儿园老是说话怎么办 在外留学想领养一个外国小孩怎么办 三岁半的宝宝想去美国上学怎么办 农村新房边的老老祖坟不搬怎么办 倒西太阳晒的房子夏天很热怎么办 客厅壁纸用的浅灰色影视墙怎么办 我喜欢玩手机游戏妈妈很生气怎么办 家里墙上有很多白色的虫子怎么办 3岁半宝宝学数字学不会怎么办 小孩子读一年级拼音读不好要怎么办 4个月的婴儿恶心干呕怎么办 生了小孩后胆汁酸偏高怎么办 9个月宝宝吃盐了怎么办 两个月宝宝母乳拉大便太稀怎么办呀 两个月的宝宝不拉大便怎么办 两个月宝宝五天没拉大便怎么办 4个月宝宝不拉大便怎么办 2个月宝宝3天没拉大便怎么办 宝宝拉不出大便老是憋的哭怎么办 九个月的宝宝不爱吃水果怎么办 顺产侧切伤口发炎化脓有臭味怎么办 一岁宝宝感冒发烧39度怎么办 宝宝二岁半了只吃水果不吃饭怎么办 8个月小孩发烧39度怎么办 咳嗽吃了很多药都不见效果怎么办 生完孩子半个月奶水越来越少怎么办 买到了坏了的水果商家不赔怎么办 小孩奶不够吃又不吃奶粉怎么办 10个月的宝宝便秘很严重怎么办 四岁的宝宝突然不怎么吃饭怎么办 1岁7个月宝宝突然不爱吃饭怎么办 宝宝发烧好了之后不吃辅食怎么办 吃母乳的宝宝不喝奶粉怎么办 奶水不足宝宝又不喝奶粉怎么办 6个月宝宝断奶哭闹不用奶瓶怎么办