It may be complicated trying to always instantiate some classes using the standard XML configuration even though creating bean definitions this way is very flexible.
To hide more complex instantiation logic the FactoryBean interface can be used. We've already seen a few examples of a FactoryBeans.
The naming convention Spring typically follows is if the FactoryBean returns a DatabaseConnectionPool
it would be called DatabaseConnectionPoolFactoryBean. Spring leverages FactoryBeans a lot for AOP, JMX, remoting, caching, and other processes.
Exactly what Spring does for some of these implementations will be discussed later.
The FactoryBean interface has three methods. The Object getObject() method returns an instance created by the factory.
The Class getObjectType() method returns the type of instance that will be returned by getObject(). If the type isn't known until runtime,
null should be returned. The final method in the interface is boolean isSingleton().
If it returns true, the same instance is always returned by the factory.
Spring also supports configuring a factory using two attributes on the bean element. A factory configured this way doesn't need to implement
the FactoryBean interface. This may help reusing an existing factory implementation or you may not want a factory to have any dependencies on Spring.
The factory-bean attribute is a reference to another bean and the factory-method attribute is
the method to call to get the instance this bean will represent. When these attributes are specified, the class attribute must be left blank.
Example 3.35. DateFactoryBean
The first bean definition shows a short date as text being set set on the DateFactoryBean. It will use
the default style pattern DateFormat.SHORT and Locale.US for processing the text. The date pattern
with this configuration is 'M/d/yyyy'. The 'M' is for the month of the year, 'd' is for the day of the month, and 'yyyy' is for a four digit year.
To see all the different formating options available read the javadocs for java.text.SimpleDateFormat.
The defaultDate bean will be a java.util.Date based on the the parsed text and will have a value of 'Sun May 30 00:00:00 EDT 1982'.
The second bean definition sets the locale to Locale.UK. The default style pattern for a short date in this locale is 'd/M/yyyy'.
Notice that the day comes before the month compared to the US. Date formats vary depending on the region.
The third bean definition sets the style pattern to medium where the month is written out.
<bean id="defaultDate"
class="org.springbyexample.springindepth.chapter03.factoryBean.DateFactoryBean">
<property name="date" value="5/30/1982" />
</bean>
<bean id="localeDate"
class="org.springbyexample.springindepth.chapter03.factoryBean.DateFactoryBean">
<property name="date" value="21/11/1974" />
<property name="locale">
<util:constant static-field="java.util.Locale.UK" />
</property>
</bean>
<bean id="mediumDate"
class="org.springbyexample.springindepth.chapter03.factoryBean.DateFactoryBean">
<property name="date" value="June 16, 1947" />
<property name="stylePattern">
<util:constant static-field="java.text.DateFormat.MEDIUM" />
</property>
</bean>
Example 3.36. XML Configured Factory
The first bean definition configures a factory, but this class doesn't implement FactoryBean.
<bean id="dateCreator"
class="org.springbyexample.springindepth.chapter03.factoryBean.DateCreator">
<property name="date" value="5/30/1982" />
</bean>
<bean id="configFactoryDate"
factory-bean="dateCreator"
factory-method="createDate" />
If there is ever a need to retrieve the actual FactoryBean and not the bean the factory creates, an '&' can be prepended to the bean name.
For example, the defaultDate bean from in the earlier example could have the FactoryBean
retrieved from the ApplicationContext by calling ctx.getBean(“&defaultDate”).