使用Spring的IoC容器
3.1 BeanFactory和ApplicationContext的介绍
3.1.1BeanFactory介绍 BeanFactory是一个类工厂,但它和传统的类工厂不同,传统的类工厂仅生成一个类的对象,或几个实现某一相同接口类的对象。而BeanFactory是通用的工厂,他可以创建和管理各种类的对象。这些可被创建和管理的对象本身没有什么特别之处,仅是一个简单的POJO,Spring称这些被创建和被管理的Java对象为Bean。我们知道JavaBean是要满足一定规范的,如必须提供一个默认不带参的构造函数、不依赖于某一特定的容器等,但Spring中所说的Bean比JavaBean更宽泛一些,所以不需要额外服务支持的POJO都可以是Bean。
Spring为BeanFactory提供了多种实现,最常用的是XmlBeanFactory。我们该如何获得一个XmlBeanFactory呢?
代码清单1
Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
或
ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
BeanFactory factory = new XmlBeanFactory(resource);
或
ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
代码清单1中我们通过FileSystemResource和ClassPathResource都获得了XmlBeanFactory。但是我们有了XmlBeanFactory对象又能干什么用呢?
代码清单2
public
class
Foo {
private
String
name
;
public
void
setName(String name) {
this
.
name
= name;
}
public
String toStirng(){
return
"Foo Name is :"
+
this
.
name
;
}
}
<?
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:p
=
"http://www.springframework.org/schema/p"
xmlns:context
=
"http://www.springframework.org/schema/context"
xsi:schemaLocation
=
"
[url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.5.xsd[/url]
[url]http://www.springframework.org/schema/context[/url] [url]http://www.springframework.org/schema/context/spring-context-2.5.xsd[/url]"
>
<
bean
id
=
"foo"
class
=
"com.tony.test.Foo"
>
<
property
name
=
"name"
value
=
"Foo"
/>
</
bean
>
</
beans
>
import
org.springframework.beans.factory.BeanFactory;
import
org.springframework.beans.factory.xml.XmlBeanFactory;
import
org.springframework.core.io.ClassPathResource;
public
class
Test {
public
static
void
main(String[] args) {
//
定义
Spring
配置文件
ClassPathResource resource =
new
ClassPathResource(
"spring-config-beans.xml"
);
//
实例化
BeanFactory
BeanFactory factory =
new
XmlBeanFactory(resource);
//
根据配置文件中的
id
获得
Bean
Foo foo = (Foo) factory.getBean(
"foo"
);
System.
out
.println(foo.toStirng());
}
}
运行结果
Foo Name is :Foo
代码清单
2
中我们首先定义了一个很普通的
java
类
Foo.java
然后在
Spring
配置文件中将其配置
,
关键的是我们的
Test.java
类我们首先实例化了
ClassPathResource
对象,在实例化时我们已经告诉了它
Spring
配置文件的名称,实例化
BeanFactory
后我们通过
factory.getBean
就可以获得由
Spring
管理的
Bean
了。我们惊奇的发现
Spring
竟然帮我们把
Foo
对象中
name
属性的数据装配进去了。
3.1.2
A
pplicationContext
介绍
如果说
BeanFactory
是
Spring
的心脏,那么
ApplicationContext
就是
Spring
的五脏六腑和躯干四肢了。
ApplicationContext
接口由
BeanFactory
派生而来,提供了更多面向实际应用的功能,在
BeanFactory
中,很多功能需要以编程的方式进行操作,而在
ApplicationContext
中则可以通过配置的方式进行控制。
简而言之,
BeanFactory提供了配制框架及基本功能,而ApplicationContext则增加了更多支持企业核心内容的功能。ApplicationContext完全由BeanFactory扩展而来,因而BeanFactory所具备的能力和行为也适用于ApplicationContext。
3.2 Bean的基本配置
每个bean都有一个或多个id(或称之为标识符或名称,在术语上可以理 解成 一回事)。这些id在当前IoC容器中必须唯一。如果一个bean有多 个id, 那么其他的id在本质上将被认为是别名。
当使用基于XML的配置元数据时,将通过
id或name属性来指定bean标识 符。 id属性具有唯一性,而且是一个真正的XML ID属性,因此其他xml 元素在引用该id时,可以利用XML解析器的验证功能。通常情况下最好为 bean指定一个id。尽管XML规范规定了XML ID命名的有效字符,但是bean 标识符的定义不受该限制,因为除了使用指定的XML字符来作为id,还可以 为bean指定别名,要实现这一点可以在name属性中使用逗号、冒号或者空 格将多个id分隔。
值得注意的是,为一个bean提供一个name并不是必须的,如果没有指定, 那么容器将为其生成一个惟一的name。
<
bean
id
=
"foo"
class
=
"com.tony.test.Foo"/
>
一般情况下,
SpringIoC
容器中的一个
Bean
即对应配置文件中的一个
<bean>
,这种镜像性的对应关系很容易理解。其中
id
为这个
Bean
的名称,通过容器的
getBean(“foo”)
即可获取对应的
Bean
,在容器中起到定位查找的作用,是外部程序和
SpringIoC
容器进行通信的桥梁。
Class
属性指定了
Bean
对应的实现类。
3.3 依赖注入
Spring支持两种依赖注入方式,分别是属性注入和构造函数注入。。
3.3.1属性注入
属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常用的注入方式。
代码清单1
public
class
Foo {
private
String
name
;
public
void
setName(String name) {
this
.
name
= name;
}
public
String toStirng(){
return
"Foo Name is :"
+
this
.
name
;
}
}
<
bean
id
=
"foo"
class
=
"com.tony.test.Foo"
>
<
property
name
=
"name"
value
=
"Foo"
/>
</
bean
>
Foo类中定义了一个属性name,并提供了对应的Setter方法,我们配置了一个Bean,并为该Bean的name属性提供了属性值。具体来说,Bean的每一个属性对应一个
<property>
标签,
name
为属性的名称,在
Bean
实现类中拥有与其的对应的
Setter
方法
name
对应
setName()
方法。
3.3.2
构造函数注入
构造函数注入是除属性注入之外的另一种常用注入方式,它保证一些必要的属性在
Bean
实例化时就得到设置,它保证了
Bean
实例在实例化后就可以使用。
代码清单
1
public
class
Foo {
private
String
name
;
private
int
age
;
public
Foo(String name,
int
age){
this
.
name
= name;
this
.
age
= age;
}
public
String toStirng(){
return
"Foo Name is :"
+
this
.
name
;
}
}
<
bean
id
=
"foo"
class
=
"com.tony.test.Foo"
>
<
constructor-arg
type
=
"int"
>
<
value
>
20
</
value
>
</
constructor-arg
>
<
constructor-arg
type
=
"java.lang.String"
>
<
value
>
Foo
</
value
>
</
constructor-arg
>
</
bean
>
代码清单
1
中我们定义了一个构造函数,接受一个
String
类型的入参,配置文件中我们配别通过
<constructor-arg>
元素中定义了
type
类型为
java.lang.String
和
int
的两个元素,
Spring
会通过
type
类型来对构造函数进行注入,因此我们在配置文件和构造函数入参顺序不同的情况下还是可以成功注入。但是我们对于多个构造函数并且类型都一样的时候我们改怎么办呢?
代码清单
2
<
bean
id
=
"foo"
class
=
"com.tony.test.Foo"
>
<
constructor-arg
index
=
"0"
value
=
"Foo"
/>
<
constructor-arg
index
=
"1"
value
=
"20"
/>
</
bean
>
只要修改配置文件中
<constructor-arg>
元素把
type
属性改为
index
并且指定参数的索引就可一了,这里一定要注意索引是从
0
开始的。
3.4 Bean
的作用域
在配置文件中定义
Bean
时,用户不单可以配置
Bean
的属性值以及相互之间的依赖关系,还可以定义
Bean
的作用域。作用域将对
Bean
的生命周期和创建方式产生影响。在低版本的
Spring
中,仅有两个作用域:
singleton
和
prototype
,在
Spring2.0
中,针对
WebApplicationContext
新增加了
3
个作用域。
singleton
<bean id="foo" class="…" scope="singleton"/>
在
SpringIoC
容器中仅存在一个
Bean
实例,
Bean
以单实例的方式存在。
prototype
<bean id="foo" class="…" scope="prototype"/>
每次从容器中调用
Bean
时,都返回一个新的实例,即每次调用
getBean
时,相当于执行
newXxxBean
的操作。
request
<
bean
id
=
"foo"
class
=
"…"
scope
=
"
request
"
/>
每次HTTP请求都会创建一个新的Bean。该作用域仅适用于WebApplicationContext环境。
session
<
bean
id
=
"foo"
class
=
"…"
scope
=
"
session
"
/>
同一个HTTPSession共享一个Bean,不同HTTPSession使用不同的Bean。该作用域仅适用于WebApplicationContext环境。
globalSession
<
bean
id
=
"foo"
class
=
"…"
scope
=
"
globalSession
"
/>
同一个全局Session共享一个Bean,一般用于Protlet应用环境。该作用域仅适用于WebApplicationContext环境。
我的其它Spring文章,也许会对您有帮助
本文转自 tony_action 51CTO博客,原文链接:http://blog.51cto.com/tonyaction/85159,如需转载请自行联系原作者