论到工厂模式,很多人都不陌生,在Spring中可以配置静态工厂(使用某个工厂类的静态方法来获取实例)和实例工厂(必须使用某个工厂类实例中的方法来获取实例)。
静态工厂配置
首先,创建工厂生产的类的相关接口,这里只是演示,所以就不附带方法了。
public interface IProduct extends Serializable {
}
接着,创建两个实现类ProductA和ProductB
@SuppressWarnings("serial")
public class ProductA implements IProduct {
}
@SuppressWarnings("serial")
public class ProductB implements IProduct {
}
创建工厂类
public class ProductFactory {
public static IProduct getInstance(Class<?> clzz)
{
if(clzz.equals(ProductA.class))
{
return new ProductA();
}
else if(clzz.equals(ProductB.class))
{
return new ProductB();
}
else
{
throw new RuntimeException("attemp to pass an argument doesn't implement interface IProduct");
}
}
}
最后,配置applicationContext.xml文件,由于静态工厂带了一个Class<?>参数,所以在传递给getInstance方法时候,应该传递一个参数进去,类参数这种类型需要使用到SpEL中的T()运算符,比如T(com.daniel.model.bean.ProducAt)实际上就是等价于java代码ProductA.class。
<bean id="product" class="com.daniel.model.bean.ProductFactory" factory-method="getInstance">
<constructor-arg value="#{T(com.daniel.model.bean.ProductB)}"></constructor-arg>
</bean>
当某个bean是使用静态工厂获取的时候,class可以指定静态工厂,factory-method则用来指定静态工厂的静态方法,而constructor-arg可以给静态工厂中的静态方法传递参数。
实例工厂配置
首先,改造一下刚刚的静态工厂,让产生实例的静态方法转变成为普通方法
public class ProductFactory {
public IProduct getInstance(Class<?> clzz)
{
if(clzz.equals(ProductA.class))
{
return new ProductA();
}
else if(clzz.equals(ProductB.class))
{
return new ProductB();
}
else
{
throw new RuntimeException("attemp to pass an argument doesn't implement interface IProduct");
}
}
}
然后再去配置applicationContext.xml文件,这时候要创建一个工厂实例,因为要通过这个实例来调用普通方法,这个bean要像普通的bean一样配置。
<bean id="product" factory-bean="factory" factory-method="getInstance">
<constructor-arg value="#{T(com.daniel.model.bean.ProductA)}"></constructor-arg>
</bean>
<bean id="factory" class="com.daniel.model.bean.ProductFactory"/>