Spring使用静态工厂方法建立Bean

1. 使用静态工厂方法建立Beanjava

    使用静态工厂方法建立Bean实例时,class属性也必须指定,但此时class属性并非指定Bean实例的实现类,而是静态工厂类。由于Spring须要知道是用哪一个工厂来建立Bean实例。另外,还须要使用factory-method来指定静态工厂方法名,Spring将调用静态工厂方法(可能包含一组参数),来返回一个Bean实例,一旦得到了指定Bean实例,Spring后面的处理步骤与采用普通方法建立Bean实例则彻底同样。须要注意的是,当使用静态工厂方法来建立Bean时,这个factory-method必需要是静态的。这段阐述听上去有点晕,话很少说,上代码:
设计模式

    先定义一个接口,静态方法产生的将是该接口的实例:
app

public interface Animal {
    public void sayHello();
}

    下面是接口的两个实现类:ide

public class Cat implements Animal {
    private String msg;
    //依赖注入时必须的setter方法
    public void setMsg(String msg){
        this.msg = msg;
    }
    @Override
    public void sayHello(){
        System.out.println(msg + ",喵~喵~");
    }
}

public class Dog implements Animal {
    private String msg;
    //依赖注入时必须的setter方法
    public void setMsg(String msg){
        this.msg = msg;
    }
    @Override
    public void sayHello(){
        System.out.println(msg + ",旺~旺~");
    }
}

    下面的AnimalFactory工厂中包含了一个getAnimal的静态方法,该方法将根据传入的参数决定建立哪一个对象。这是典型的静态工厂设计模式。
测试

public clas AnimalFactory {
    public static Animal getAnimal(String type){
        if ("cat".equalsIgnoreCase(type)){
            return new Cat();
        } else {
            return new Dog();
        }
    }
}

    若是须要指定Spring使用AnimalFactory来产生Animal对象,则可在Spring配置文件中做以下配置:this

<!-- 配置AnimalFactory的getAnimal方法,使之产生Cat -->
<bean id="cat" class="com.abc.AnimalFactory" factory-method="getAnimal">
    <!-- 配置静态工厂方法的参数,getAnimal方法将产生Cat类型的对象 -->
    <constructor-arg value="cat" />
    <!-- 经过setter注入的普通属性 -->
    <property name="msg" value="猫猫" />
</bean>
<!-- 配置AnimalFactory的getAnimal方法,使之产生Dog -->
<bean id="dog" class="com.abc.AnimalFactory" factory-method="getAnimal">
    <!-- 配置静态工厂方法的参数,getAnimal方法将产生Dog类型的对象 -->
    <constructor-arg value="dog" />
    <!-- 经过setter注入的普通属性 -->
    <property name="msg" value="狗狗" />
</bean>

    从上面的配置能够看出:cat和dog两个Bean配置的class和factory-method彻底相同,这是由于两个实例都使用同一个静态工厂类、同一个静态工厂方法产生获得的。只是为这个静态工厂方法指定的参数不一样,使用<constructor-arg />元素来为静态工厂方法指定参数。
spa

    主程序获取cat和dog两个Bean实例的方法不变,一样只须要调用Spring容器的getBean()便可:
设计

public class Test {
    public static void main(String args[]){
        ApplicationContext context = 
                new ClassPathXmlApplicationContext("applicationContext.xml");
        Animal a1 = context.getBean("cat", Animal.class);
        a1.sayHello();
        Animal a2 = context.getBean("dog", Animal.class);
        a2.sayHello();
    }
}

    输出结果:code

猫猫,喵~喵~
狗狗,旺~旺~

    使用静态工厂方法建立实例时必须提供工厂类和产生实例的静态工厂方法。经过静态工厂方法建立实例时须要对Spring配置文件作以下改变;
xml

  • class属性不在是Bean实例的实现类,而是生成Bean实例的静态工厂类

  • 使用factory-method指定生产Bean实例的静态工厂方法

  • 若是静态工厂方法须要参数,使用<constructor-arg />元素为其配置

    当咱们指定Spring使用静态工厂方法来建立Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,经过反射调用静态工厂类的静态工厂方法,并将该静态工厂方法的返回值做为Bean实例,在这个过程当中,Spring再也不负责建立Bean实例,Bean实例是由用户提供的静态工厂方法提供的。


2. 使用实例工厂方法建立Bean

    实例工厂方法与静态工厂方法只有一点不一样:调用静态工厂方法只须要使用工厂类便可,调用实例工厂方法则必须使用工厂实例。因此在Spring配置上也只有一点区别:配置静态工厂方法指定静态工厂类,配置实例工厂方法则指定工厂实例。一样是上面的例子将AnimalFactory修改成:

public clas AnimalFactory {
    public Animal getAnimal(String type){  //这里仅仅是去掉了static关键字
        if ("cat".equalsIgnoreCase(type)){
            return new Cat();
        } else {
            return new Dog();
        }
    }
}

    Spring文件修改成:

<!-- 先配置工厂类 -->
<bean id="animalFactory" class="com.abc.AnimalFactory" />
<!-- 这里使用factory-bean指定实例工厂类对象 -->
<bean id="cat" factory-bean="animalFactory" factory-method="getAnimal">
    <!-- 一样指定factory-method的参数 -->
    <constructor-arg value="cat" />
    <property name="msg" value="猫猫" />
</bean>

<bean id="dog" factory-bean="animalFactory" factory-method="getAnimal">
    <constructor-arg value="dog" />
    <property name="msg" value="狗狗" />
</bean>

    测试类不用修改,输出结果和上面相同。

相关文章
相关标签/搜索