????? 如果bean無(wú)法簡(jiǎn)單地通過(guò)new關(guān)鍵字來(lái)創(chuàng)建怎么辦,通常碰到這樣的情況時(shí),我們都會(huì)使用工廠模式來(lái)處理,Spring也提供了對(duì)FactoryBean的支持,當(dāng)我們配置了一個(gè)bean為FactoryBean時(shí),隨后我們獲取的則并不是該FactoryBean,Spring會(huì)通過(guò)調(diào)用FactoryBean.getObject()方法,返回真正的目標(biāo)bean。FactoryBean在Spring中的最著名應(yīng)用就是對(duì)聲明式事務(wù)的處理。
????? 在Spring中使用FactoryBean,我們需要編寫(xiě)一個(gè)實(shí)現(xiàn)了FactoryBean接口的類(lèi),以一個(gè)信息摘要FactoryBean為例,它主要實(shí)現(xiàn)根據(jù)不同的參數(shù),創(chuàng)建不同的MessageDigest的實(shí)例。
public class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
??? private String algorithmName = "MD5";
??? private MessageDigest messageDigest = null;
??? public Object getObject() throws Exception {
??????? return messageDigest.clone();
??? }
??? public Class getObjectType() {
??????? return MessageDigest.class;
??? }
??? public boolean isSingleton() {
??????? return true;
??? }
??? public void afterPropertiesSet() throws Exception {
??????? messageDigest = MessageDigest.getInstance(algorithmName);
??? }
??? public void setAlgorithmName(String algorithmName) {
??????? this.algorithmName = algorithmName;
??? }
}
?????
getObject方法是供Spring調(diào)用,用來(lái)返回真正的bean給其它bean的(而不是FactoryBean本身),getObjectType方法可以返回null,但如果指定了類(lèi)型,就可以使用Spring的自動(dòng)裝載功能了。isSingleton方法是指定bean是否是單例的,注意不能通過(guò)FactoryBean的配置文件來(lái)指定bean是否為單例,因?yàn)槟菢又付ǖ氖荈actoryBean本身,而不是真正的目標(biāo)bean。
????? FactoryBean的配置和普通bean并沒(méi)有什么區(qū)別。
????? 由于Bean配置文件中,各個(gè)屬性都是以String的形式配置的(除了使用ref引用其它bean外),因此,Spring在組裝bean的時(shí)候,需要把String類(lèi)型的值轉(zhuǎn)化成合適的類(lèi)型,這就需要用到JavaBean中的概念:PropertyEditor。
????? Spring內(nèi)置了7種預(yù)先注冊(cè)的PropertyEditor:ByteArrayPropertyEditor,ClassEditor,F(xiàn)ileEditor,LocaleEditor,PropertiesEditor,StringArrayPropertyEditor,URLEditor。通過(guò)名字,我們就能清楚地知道它們對(duì)應(yīng)的類(lèi)型了。
????? 盡管內(nèi)置的PropertyEditor可以處理大部分常見(jiàn)的類(lèi)型,我們?nèi)匀粫?huì)碰到需要?jiǎng)?chuàng)建自己的PropertyEditor的情況。為了簡(jiǎn)化自定義PropertyEditor的創(chuàng)建,Spring提供了PropertyEditorSupport類(lèi),我們只需要擴(kuò)展該類(lèi),并實(shí)現(xiàn)其中的setAsText方法即可。
public class PatternPropertyEditor extends PropertyEditorSupport {
??? public void setAsText(String text) throws IllegalArgumentException {
??????? Pattern pattern = Pattern.compile(text);
??????? setValue(pattern);
??? }
}
????? 可以看到,實(shí)現(xiàn)一個(gè)自定義的PropertyEditor是很容易的,但怎么才能讓它起作用呢,也就是通常所說(shuō)的注冊(cè)PropertyEditor。Spring提供了兩種注冊(cè)的方式:1.通過(guò)ConfigurableBeanFactory的registerCustomEditor方法;2.在BeanFactory的配置文件中定義CustomEditorConfigurer。
<bean name="customEditorConfigurer"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
??? <property name="customEditors">
??????? <map>
??????????? <entry key="java.util.regex.Pattern">
??????????????? <bean class="com.apress.prospring.ch5.pe.PatternPropertyEditor"/>
??????????? </entry>
??????? </map>
??? </property>
</bean>
????? 自定義的PropertyEditor是通過(guò)CustomEditorConfigurer的一個(gè)類(lèi)型為Map的屬性添加的,key值是自定義PropertyEditor對(duì)應(yīng)的類(lèi)型的全類(lèi)名。
??????在使用時(shí)需要先調(diào)用:
CustomEditorConfigurer config =
??? (CustomEditorConfigurer) factory.getBean("customEditorConfigurer");
config.postProcessBeanFactory(factory);
????? 來(lái)將所有自定義的ProperyEditor注冊(cè)到BeanFactory中。