装配
Bean
是
Spring
的一个非常重要的功能。我们可以通过
Spring
在
XML
文件中配置
Java Bean
,然后通过
ApplicationContext
来获得
Bean
的对象实例。在配置
Bean
时,需要对构造方法的参数,属性进行初始化。对于
Java
简单类型或简单类型的
List
、
Map
等数据类型初始化非常简单,如下面就是一个对简单类型属性和构造方法参数进行初始化的配置代码:
但对于复杂类型的属性或参数,如一个属性的类型是另外一个 Java Class ,这样就必须在配置文件中再声明这个 Java Class ,如果这种情况很多时,或是我们做的类要 release 时,就会给开发人员增加很多工作量。让我们先来举个例子。假设有两个类: Contact 和 PhoneNumber , Contact 的 phoneNumber 属性的类型是 PhoneNumber ,代码如下:
PhoneNumber类
如果直接在 XML 配置文件中装配 Contact 类,就需要先装配 PhoneNumber 类,代码如下:
这个类的代码非常简单,在 setAsText 方法中只有一行代码,实际上只是建立一个 PhoneNumber 对象实例,并将 text 属性值作为参数值传入 PhoneNumber 的构造方法。接下来我们在配置文件中安装这个属性编辑器(实际上是装配 org.springframework.beans.factory.config.CustomEditorConfigurer 类),代码如下:
从上面的代码可以看出,属性编辑器是使用了 CustomEditorConfigurer 的 customEditors 属性进行安装的。这是一个 Map 类型的属性。 key 的值必须是属性编辑器最终转换后的类型名,如在本例中,要将文本的参数值转换成 bean.PhoneNumber 类型的值,因此, key 必须为 bean.PhoneNumber 。 下面我们来使用 PhoneEditor 属性编辑器类来装配 Contact 类,代码如下:
import org.springframework.context. * ;
import org.springframework.context.support. * ;
public class Test
{
public static void main(String[] args)
{
// 上面的配置代码都在applicationContext.xml文件中
ApplicationContext context = new FileSystemXmlApplicationContext( " src\\applicationContext.xml " );
bean.Contact contact = (bean.Contact) context.getBean( " contact " );
System.out.println(contact.getPhoneNumber().getNumber());
}
}
<!--
要求Spring2.0或Spring2.5 scope="prototype"相当于Spring1.x的singleton="false"
-->
< bean id ="my" class ="bean.MyClass" scope ="prototype" >
< constructor-arg >
< value > my value1 </ value >
</ constructor-arg >
< property name ="name" >
< value > 皮球 </ value >
</ property >
< property name ="myList" >
< list >
< value > value1 </ value >
< value > value2 </ value >
</ list >
</ property >
</ bean >
< bean id ="my" class ="bean.MyClass" scope ="prototype" >
< constructor-arg >
< value > my value1 </ value >
</ constructor-arg >
< property name ="name" >
< value > 皮球 </ value >
</ property >
< property name ="myList" >
< list >
< value > value1 </ value >
< value > value2 </ value >
</ list >
</ property >
</ bean >
但对于复杂类型的属性或参数,如一个属性的类型是另外一个 Java Class ,这样就必须在配置文件中再声明这个 Java Class ,如果这种情况很多时,或是我们做的类要 release 时,就会给开发人员增加很多工作量。让我们先来举个例子。假设有两个类: Contact 和 PhoneNumber , Contact 的 phoneNumber 属性的类型是 PhoneNumber ,代码如下:
Contact
类
package
bean;
public class Contact
{
private PhoneNumber phoneNumber;
public PhoneNumber getPhoneNumber()
{
return phoneNumber;
}
public void setPhoneNumber(PhoneNumber phoneNumber)
{
this .phoneNumber = phoneNumber;
}
}
public class Contact
{
private PhoneNumber phoneNumber;
public PhoneNumber getPhoneNumber()
{
return phoneNumber;
}
public void setPhoneNumber(PhoneNumber phoneNumber)
{
this .phoneNumber = phoneNumber;
}
}
PhoneNumber类
package
bean;
public class PhoneNumber
{
private String number;
public PhoneNumber(String s)
{
this .number = s;
}
public String getNumber()
{
return number;
}
}
public class PhoneNumber
{
private String number;
public PhoneNumber(String s)
{
this .number = s;
}
public String getNumber()
{
return number;
}
}
如果直接在 XML 配置文件中装配 Contact 类,就需要先装配 PhoneNumber 类,代码如下:
<?
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:tx ="http://www.springframework.org/schema/tx"
xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" >
< bean id ="contact" class ="bean.Contact" >
< property name ="phoneNumber" >
< ref bean ="phoneNumber" />
</ property >
</ bean >
< bean id ="phoneNumber" class ="bean.PhoneNumber" >
< constructor-arg >
< value > 12345678 </ value >
</ constructor-arg >
</ bean >
</ beans >
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx ="http://www.springframework.org/schema/tx"
xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" >
< bean id ="contact" class ="bean.Contact" >
< property name ="phoneNumber" >
< ref bean ="phoneNumber" />
</ property >
</ bean >
< bean id ="phoneNumber" class ="bean.PhoneNumber" >
< constructor-arg >
< value > 12345678 </ value >
</ constructor-arg >
</ bean >
</ beans >
从上面的代码中可以看到,装载Contact
的同时,也装载了PhoneNumber
。但如果使用了属性编辑器,就可以无需装载PhoneNumber
就可以装载Contact
了。
编写自己的属性编辑器的步骤很简单,属性编辑器类需要从
java.beans.PropertyEditorSupport
类继承,在这个类中有一个
setAsText
方法,这个方法有一个
String
类型的参数,通过这个方法,可以将
String
类型的参数值转换成其他类型的属性。在这个方法中我们还需要使用一个
setValue
方法,就来指定转换后的对象实例。好,现在我们来实现这个简单的编辑器类,代码如下:
package
editor;
public class PhoneEditor extends java.beans.PropertyEditorSupport
{
@Override
public void setAsText(String text) throws IllegalArgumentException
{
setValue( new bean.PhoneNumber(text));
}
}
public class PhoneEditor extends java.beans.PropertyEditorSupport
{
@Override
public void setAsText(String text) throws IllegalArgumentException
{
setValue( new bean.PhoneNumber(text));
}
}
这个类的代码非常简单,在 setAsText 方法中只有一行代码,实际上只是建立一个 PhoneNumber 对象实例,并将 text 属性值作为参数值传入 PhoneNumber 的构造方法。接下来我们在配置文件中安装这个属性编辑器(实际上是装配 org.springframework.beans.factory.config.CustomEditorConfigurer 类),代码如下:
<
bean
id
="customerEditor"
class ="org.springframework.beans.factory.config.CustomEditorConfigurer" >
< property name ="customEditors" >
< map >
< entry key ="bean.PhoneNumber" >
< bean id ="phoneEditor" class ="editor.PhoneEditor" />
</ entry >
</ map >
</ property >
</ bean >
class ="org.springframework.beans.factory.config.CustomEditorConfigurer" >
< property name ="customEditors" >
< map >
< entry key ="bean.PhoneNumber" >
< bean id ="phoneEditor" class ="editor.PhoneEditor" />
</ entry >
</ map >
</ property >
</ bean >
从上面的代码可以看出,属性编辑器是使用了 CustomEditorConfigurer 的 customEditors 属性进行安装的。这是一个 Map 类型的属性。 key 的值必须是属性编辑器最终转换后的类型名,如在本例中,要将文本的参数值转换成 bean.PhoneNumber 类型的值,因此, key 必须为 bean.PhoneNumber 。 下面我们来使用 PhoneEditor 属性编辑器类来装配 Contact 类,代码如下:
<
bean
id
="contact"
class
="bean.Contact"
>
< property name ="phoneNumber" >
< value > 87654321 </ value >
</ property >
</ bean >
< property name ="phoneNumber" >
< value > 87654321 </ value >
</ property >
</ bean >
也许大家都注意到了上面这段代码的变化,在设置phoneNumber
属性默认值时,不再使用<ref>
标签来引用phoneNumber
对象,而是直接使用了<value>
来设置一个文本的电话号。Spring
当遇到这种情况时,也就是说,某个属性值和属性类型不一致时(如本例中一个是文本,一个是PhoneNumber
类型),会先找一下属性类型是否有相应的属性编辑器已经被安装,在本例中将以bean.PhoneNumber
作为key
来查找,正好找到上面安装的PhoneEditor
,因此,Spring
就会调用PhoneEditor
类中的setAsValue
方法来设置PhoneNumber
对象实例,然后Spring
在内部又分调用getValue
来获得PhoneNumber
对象实例,并将其赋给Contact
的phoneNumber
属性。其实所有类型的bean.PhoneNumber
的属性都可以使用这个属性编辑器。
大家可以看看,这样做是不是简单的多!尤其是在发布通用的framework
或程序时,就更为简单了。在Spring
中已经定义了很多这种属性编辑器,如我们可以使用org.springframework.beans.propertyeditors.URLEditor
将字符串映射成java.net.URL
对象。
下面的代码通过
ApplicationContext
来获得
Contact
的对象实例,并输出其
phoneNumber
属性值:
import org.springframework.context. * ;
import org.springframework.context.support. * ;
public class Test
{
public static void main(String[] args)
{
// 上面的配置代码都在applicationContext.xml文件中
ApplicationContext context = new FileSystemXmlApplicationContext( " src\\applicationContext.xml " );
bean.Contact contact = (bean.Contact) context.getBean( " contact " );
System.out.println(contact.getPhoneNumber().getNumber());
}
}
注:实际上,属性编辑器本身是由Java提供了,Spring只是利用了这一特性使装配一个Bean更容易而已。
本文转自 androidguy 51CTO博客,原文链接:
http://blog.51cto.com/androidguy/216458
,如需转载请自行联系原作者