本书可作为王富强所著<<Spring揭秘>>一书的读书笔记 
第四章 BeanFactory的xml之旅

bean的scope

scope有时被翻译为"作用域",scope用来声明容器中的对象所应该处的限定场景或者说该对象的存活时间,即容器在对象进入其相应的scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象。
scope共有5个,singleton,prototype,request,session,global session
前两个是通用的,中间三个只是在web系统中才才用到,最后一个global session只有应用在基于portlet的Web应用程序中才有意义,它映射到portlet的global范围的session。
我们可以通过使用<bean>的singleton或者scope属性来指定相应对象的scope,其中,scope属性只能在 SD格式的文档声明中使用,类似于如下代码所演示的形式:   
DTD: 
<bean id="mockObject1" class="...MockBusinessObject" singleton="false"/> 
XSD: 
<bean id="mockObject2" class="...MockBusinessObject"  scope="prototype"/>

singleton

singleton:容器中只有一个对象,谁要都是这个一个。只有容器不销毁或者退出,她就一直存在。
配置情况,因为scope默认的就是singleton,下面三种方式效果一样。
<!-- DTD or XSD --> 
<bean id="mockObject1" class="...MockBusinessObject"/> 
<!-- DTD --> 
<bean id="mockObject1" class="...MockBusinessObject" singleton="true"/> 
<!-- XSD --> 
< bean id="mockObject1" class="...MockBusinessObject" scope="singleton"/>

prototype

prototype:每次请求都是一个新的对象。而且,一旦这个新的对象给了请求方,那么容器就不在持有对这个对象的引用。就像嫁出去的姑娘,泼出去的水,娘家以后不管了。
配置方式:
<!-- DTD --> 
<bean id="mockObject1" class="...MockBusinessObject" singleton="false"/> 
<!-- XSD --> 
<bean id="mockObject1" class="...MockBusinessObject"  scope="prototype"/>

request

request:和prototype没什么区别,在web情况下每来一个请求,分配一个实例。
配置方式
<bean id="requestProcessor" class="...RequestProcessor"  scope="request"/>

session

session:对于放到session中的信息,可以将scope设置为session,它除了比request更长的存活时间外,其他方面没什么区别。
配置方式:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

工厂方法与FactoryBean

我们看下面的代码:

public class Foo
{ private BarInterface barInstance; public Foo()    { // 我们应该避免这样做 // instance = new BarInterfaceImpl(); } // ...
}  

为什么要避免这么做?
因为接口与实现类之间有了耦合。
有了耦合咋了,为什么就不能有耦合。
如果我不想用BarInterfaceImpl,先换成Bar2InterfaceImpl。
上面的方法就是得改Foo类的编码,如果n个类中都有instance = new BarInterfaceImpl(); 那么我岂不是得要改n处。
另一方面,如果实现类(例如barInstance)是来自外部jar包的,你没办法把它纳入spring的管理范围,哪有如何?
为之奈何?

工厂方法

public class Foo { private BarInterface barInterface;    public Foo() { // barInterface = BarInterfaceFactory.getInstance(); // 或者 // barInterface = new BarInterfaceFactory().getInstance(); } ...
}  

这样一来,Foo直接依赖于BarInterfaceFactory。如果产品有了变化,我只用改工厂,而不用"告诉"每一个使用者产品改变了。

静态工厂方式

public class StaticBarInterfaceFactory { public static BarInterface getInstance()   { return new BarInterfaceImpl(); }
}  

Foo中的BarInterface有对应的get/set方法。
要想通过静态工厂把BarInterfaceImpl注入到Foo中,我们可以这样
xml如下:

<bean id="foo" class="...Foo"> <property name="barInterface"> <ref bean="bar"/> </property>
</bean> <bean id="bar" class="...StaticBarInterfaceFactory" factory-method="getInstance"/>  

bean中有了factory-method,就说明这个类并不是使用默认的构造方法产生的,而是使用getInstance方法。再换句话说,bar这个bean最后的返回不是StaticBarInterfaceFactory,而是getInstance这个方法的返回值。
如果getInstacne需要参数呢?例如:

public class StaticBarInterfaceFactory { public static BarInterface getInstance(Foobar foobar) { return new BarInterfaceImpl(foobar); }
} 

xml如下:

<bean id="foo" class="...Foo"> <property name="barInterface"> <ref bean="bar"/> </property>
</bean> <bean id="bar" class="...StaticBarInterfaceFactory" factory-method="getInstance"> <constructor-arg> <ref bean="foobar"/> </constructor-arg>
</bean> <bean id="foobar" class="...FooBar"/>  

只有bar中的constructor-arg下的参数是给getInstance用的,而不是StaticBarInterfaceFactory。(另一方面,静态工厂也没有显示的构造方法呀)

非静态工厂方式

public class NonStaticBarInterfaceFactory {public BarInterface getInstance() { return new BarInterfaceImpl(); }   ...
} 

因为工厂方法为非静态的,我们只能通过某个NonStaticBarInterfaceFactory实例来调用该方法(哦,错了,是容器来调用),那么也就有了如下的配置内容:

<bean id="foo" class="...Foo"> <property name="barInterface"> <ref bean="bar"/> </property>
</bean> <bean id="barFactory" class="...NonStaticBarInterfaceFactory"/>
<bean id="bar" factory-bean="barFactory" factory-method="getInstance"/> 

bar这个bean,中有factory-bean这个属性,就是告诉容器,bar=barFactory.getInstance();
如果barFactoy的getinstance也需要参数呢?
同样使用:<constructor-arg>

FactoryBean

上面写的工厂方法还有一个替代方法,就是FactoryBean
FactoryBean是Spring容器提供的一种可以扩展容器对象实例化逻辑的接口,请不要将其与容器名称BeanFactory相混淆。FactoryBean,其主语是Bean,定语为Factory,也就是说,它本身与其他注册到容器的对象一样,只是一个Bean而已,只不过,这种类型的Bean本身就是生产对象的工厂(Factory)。 
我们先看看FactoryBean的签名。

public interface FactoryBean { Object getObject() throws Exception; Class getObjectType(); //如果不能确定返回的类型,getObjectType就返回nullboolean isSingleton();
}  

完全能看懂,没有压力呀。
如果我们想每次得到的日期都是第二天,可以使用如下的代码

import org.joda.time.DateTime;
import org.springframework.beans.factory.FactoryBean; public class NextDayDateFactoryBean implements FactoryBean { public Object getObject() throws Exception { return new DateTime().plusDays(1); } public Class getObjectType() { return DateTime.class; } public boolean isSingleton() { return false; } } 

要使用NextDayDateFactoryBean,只需要如下这样将其注册到容器即可:

<bean id="nextDayDateDisplayer" class="...NextDayDateDisplayer"> <property name="dateOfNextDay"> <ref bean="nextDayDate"/> </property>
</bean> <bean id="nextDayDate" class="...NextDayDateFactoryBean">
</bean>

从xml配置上似乎和以前没有什么差别,但是nextDayDateDisplayer里的属性dateOfNextDay并不是NextDayDateFactoryBean而是NextDayDateFactoryBean中getObject方法返回的对象。

public class NextDayDateDisplayer { private DateTime dateOfNextDay; // 相应的setter方法 // ...
} 

如果一定要取得FactoryBean本身的话,可以通过在bean定义的id之前加前缀&来达到目的。

Object nextDayDate = container.getBean("nextDayDate");
assertTrue(nextDayDate instanceof DateTime);
Object factoryBean = container.getBean("&nextDayDate");
assertTrue(factoryBean instanceof FactoryBean);
assertTrue(factoryBean instanceof NextDayDateFactoryBean); Object factoryValue = ((FactoryBean)factoryBean).getObject();
assertTrue(factoryValue instanceof DateTime);
assertNotSame(nextDayDate, factoryValue);
ssertEquals(  ((DateTime)nextDayDate).getDayOfYear(),((DateTime)factoryValue).getDayOfYear()   ); 

感谢glt

Spring揭秘 读书笔记 三 bean的scope与FactoryBean相关推荐

  1. Spring框架学习笔记(三)(AOP,事务管理)

    Spring框架学习笔记(三) 九.AOP 9.1 AOP的注解配置 (1) 新建计算器核心功能(模拟:不能在改动核心代码) (2) 建立一个普通的Java类写增强代码(面向切面编程),使用Sprin ...

  2. mysql数据库权威指南_MySQL_MySQL权威指南读书笔记(三),第二章:MYSQL数据库里面的数 - phpStudy...

    MySQL权威指南读书笔记(三) 第二章:MYSQL数据库里面的数据 用想用好MYSQL,就必须透彻理解MYSQL是如何看待和处理数据的.本章主要讨论了两个问题:一是SQL所能处理的数据值的类型:二是 ...

  3. 《编程之美》读书笔记(三):烙饼问题与搜索树

    <编程之美>读书笔记三:烙饼问题与搜索树 薛笛 EMail:jxuedi#gmail.com 前面已经写了一些关于烙饼问题的简单分析,但因为那天太累有些意犹未尽,今天再充实一些内容那这个问 ...

  4. 《How Tomcat Works》读书笔记(三)--Connector(连接器)

    <How Tomcat Works>读书笔记(三)--Connector(连接器) 这是<How Tomcat Works>第三四章的读书笔记.主要写了Tomcat4.0默认的 ...

  5. TCPIP详解Protocol 读书笔记(三) IP协议讲解

    TCP/IP详解:Protocol 读书笔记(三) Chapter3 IP:网际协议 文章目录 TCP/IP详解:Protocol 读书笔记(三) Chapter3 IP:网际协议 IP协议 IP数据 ...

  6. 《spring揭秘》读书笔记三

    bean的scope 1. singleton, scope默认值为singleton spring容器中 scope='singleton'与单例模式不是一个意思.标记为singleton的bean ...

  7. 《Spring》(六)---- Bean的scope

    Bean的scope 配置中的bean定义可以看作是一个模板,容器会根据这个模板来构造对象,但是要根据这个模板构造多少个对象,又该让这些构造完的对象实例存活多久,则由容器的scope定义.scope用 ...

  8. 《大型网站技术架构》读书笔记三:大型网站核心架构要素

    来源:http://www.cnblogs.com/edisonchou/p/3806348.html 此篇已收录至<大型网站技术架构>读书笔记系列目录贴,点击访问该目录可获取更多内容. ...

  9. Spring boot 源码:Bean的Scope

    1.美图 2.概述 Scope描述的是Spring容器如何创建新Bean的实例.Spring的Scope有以下几种,通过@Scope注解来实现. Singleton:一个Spring容器中只有一个Be ...

最新文章

  1. 五边形创意画_绝了,自己做吊灯,创意满满!不仅好看还省钱!
  2. MOCTF-Web-还是水题
  3. 为什么说产品经理都该懂一点机器学习?
  4. My Appointment编辑场景下的roundtrip
  5. django 静态数据_如何在Django中使用静态数据?
  6. 【Leetcode | 48】226. 翻转二叉树
  7. eclipse搜索框太小
  8. 【HDU - 1518】Square (经典的dfs + 剪枝)
  9. android 线性布局蒙层,Android开发 - 掌握ConstraintLayout(一)传统布局的问题
  10. Linux笔记-bash批量启动、停止、重启、查询状态指定Java进程(其他进行通用)
  11. 第十章:禁丹药,禁符纸
  12. VUe3 @cli(axios)跨域访问
  13. java 使用apollo,Springboot apollo原理及使用方法详解
  14. 万万没想到之抓捕孔连顺
  15. firefox浏览器和IE
  16. 如何在VS2015创建C语言项目
  17. Logism · 原码一位乘法器 实验
  18. DelayQueue用例
  19. 微信公众号编辑模式下推送消息
  20. React路由ReactRouter6

热门文章

  1. 一堆让人激动的头像生成器,太香了!-搜嗖工具箱
  2. 【人工智能】“可信”人工智能决策框架及实践
  3. MSDN微软原版软件
  4. 博菲电气深交所上市:市值23亿 为陆云峰与凌莉夫妻店
  5. ftp服务器老是显示登录界面,登录ftp服务器总提示登陆框
  6. 使用C#制作Windows窗体应用,实现一个微端下载器功能(多线程/断点续传/微端/下载器)
  7. 测试工程师的必备Adb命令!!!
  8. soft Windows精品软件收集
  9. 基于wireshark的HTTP请求报文分析
  10. niushop打包云闪付小程序,调起云闪付授权登录