FactoryBean
和BeanFactory
由于在命名上极其相似,一直以来困扰了不少的开发者。
BeanFactory
,耳熟能详的Spring核心接口,提供IoC容器的最基本功能。但要解释FactoryBean
一句话可能就说不清楚了。我们将从下面的例子逐步说明,FactoryBean是什么,它提供了什么样的能力。
/** * 布料 * 包含颜色属性 * Created by OKevin On 2019/9/3 **/ public class Cloth { private Red red; //省略setter/getter方法 }
当初始化一个Cloth对象时,我希望Red对象也被赋值,此时我将在Cloth的构造方法中new一个Red对象。
public Cloth() { red = new Red(); }
但是随着业务的发展,我希望Cloth的颜色属性将是Blue蓝色,这时我将修来源gaodai#ma#com搞@代~码$网改代码将Red和Blue类抽象出一个Color接口,Cloth代码将重构:
/** * 布料 * 包含颜色属性 * Created by OKevin On 2019/9/3 **/ public class Cloth { private Color color; public Cloth() { color = new Blue(); } //省略setter/getter方法 }
业务又进一步发展,Cloth类中的颜色属性将会根据一定的条件赋值为Red红色,此时我们将代码继续重构:
/** * 布料 * 包含颜色属性 * Created by OKevin On 2019/9/3 **/ public class Cloth { private Color color; public Cloth() { if (condition()) { color = new Blue(); } else { color = new Red(); } } //省略setter/getter方法 }
这样的代码的确能运行,但如果有新的条件继续加入到业务中,此时我们又将改动Cloth类的构造方法,而我们认为Cloth方法是一个比较核心的业务对象,不应该经常对它进行修改,并且在构造方法中对于Color对象创建过于冗余,不符合单一职责的原则,所以我们将Color对象的创建过程通过工厂方法模式来完成。
静态工厂方法
我们再次将Cloth类进行如下重构(为了使示例代码更加简洁,下面的示例将只创建Red对象):
/** * 布料 * 包含颜色属性 * Created by OKevin On 2019/9/3 **/ public class Cloth { private Color color; public Cloth() { color = StaticColorFactory.newInstance(); } //省略setter/getter方法 }
/** * 静态工厂方法 * Created by OKevin On 2019/9/3 **/ public class StaticColorFactory { public static Color getInstance() { return new Red(); } }
如果我们在Spring容器中要通过静态工厂方法,创建具体的对象实例应该怎么做呢?
众所周知,要将一个对象实例交由Spring容器管理,我们通常是通过以下XML配置:
<bean id="cloth" class="com.coderbuff.bean.Cloth"> <property name="color" ref="red"/> </bean> <bean id="red" class="com.coderbuff.bean.Red" />
但此时,Red对象实例并不是由Spring容器管理,而是由静态工厂方法创建的,此时我们应该讲XML配置修改为以下方式:
<bean id="cloth" class="com.coderbuff.bean.Cloth"> <property name="color" ref="red"/> </bean> <bean id="red" class="com.coderbuff.factory.StaticColorFactory" factory-method="getInstance" />
这是Spring支持静态工厂方法创建对象实例的特定方式。这样我们就能在Spring中通过静态工厂方法创建对象实例。