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

Easter79
• 阅读 1006

1. 使用静态工厂方法创建Bean

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

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

public interface Animal {
    public void sayHello();
}

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

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配置文件中作如下配置:

<!-- 配置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完全相同,这是因为两个实例都使用同一个静态工厂类、同一个静态工厂方法产生得到的。只是为这个静态工厂方法指定的参数不同,使用元素来为静态工厂方法指定参数。

    主程序获取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();
    }
}

    输出结果:

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

    使用静态工厂方法创建实例时必须提供工厂类和产生实例的静态工厂方法。通过静态工厂方法创建实例时需要对Spring配置文件做如下改变;

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

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

  • 如果静态工厂方法需要参数,使用元素为其配置

    当我们指定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>

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

点赞
收藏
评论区
推荐文章
Easter79 Easter79
3年前
SpringIOC官方文档解读
IoC容器本章介绍了Spring的控制反转(IoC)容器。1.1。SpringIoC容器和Bean简介本章介绍了反转控制(IoC)原则的Spring框架实现。IoC也称为依赖注入(DI)。在此过程中,对象可以通过①构造函数参数(),②工厂方法的参数③或在构造或从工厂方法返回后在对象实例上设置的属性来定义其依
Stella981 Stella981
3年前
Spring 学习笔记(三):Spring Bean
1Bean配置Spring可以看做是一个管理Bean的工厂,开发者需要将Bean配置在XML或者Properties配置文件中。实际开发中常使用XML的格式,其中<bean中的属性或子元素如下:id:Bean在BeanFactory中的唯一标识,在代码中通过BeanFac
Wesley13 Wesley13
3年前
Java设计模式之三种工厂模式
工厂模式实现了创建者和调用者的分离,实现了更好的解耦。详细分类:1)简单工厂模式(静态工厂模式);2)工厂方法模式;3)抽象工厂模式面向对象设计的基本原则:1)      OCP(开闭原则,OpenClosedPrinciple):一个软件的实体应当对扩展开放,对修改关闭。2)      
Stella981 Stella981
3年前
SpringAOP源码跟踪及学习
Spring版本4.3.2在拿到Bean实例以后,会经历一系列的初始化工作,如:工厂回调、init方法、后处理器在Bean初始化前后的处理等,在一般情况下(非factorymethod创建的Bean等),AOP代理对象的创建就在后处理器的处理方法中实现。入口以AbstractAutowireCapableB
Wesley13 Wesley13
3年前
IOC的使用
1.概要:在spring中,都是使用反射机制创建对象,将创建对象的权利交给spring容器,就是控制反转(ioc)对象创建方式有参构造无参构造工厂模式(静态,非静态)2.创建IDEA控制台测试项目!(https://oscimg.oschina.net/oscnet/a77ea6a2907139751d63
Wesley13 Wesley13
3年前
Unity C# 设计模式(二)简单工厂模式
定义:简单工厂模式是属于创建型模式,又叫做静态工厂方法(StaticFactoryMethod)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该
Easter79 Easter79
3年前
Spring实例化Bean的三种方法
实例化Bean有三种方式,分别是构造器实例化、静态工厂方式实例化和实例工厂方式实例化。本节将针对这三种方式分别进行讲解。构造器实例化构造器实例化是指Spring容器通过Bean对应的类中默认的构造函数实例化Bean。下面通过案例演示如何使用构造器实例化Bean。1\.创建项目并导入JAR包在MyEclipse中
Easter79 Easter79
3年前
Spring高级应用之注入嵌套Bean
在Spring中,如果某个Bean所依赖的Bean不想被Spring容器直接访问,可以使用嵌套Bean。和普通的Bean一样,使用<bean元素来定义嵌套的Bean,嵌套Bean只对它的外部的Bean有效,Spring容器无法直接访问嵌套的Bean,因此定义嵌套Bean也无需指定id属性。如下配置片段是一个嵌套Bean的示例:<bean id
Stella981 Stella981
3年前
Effective Java 笔记(一)
创建和销毁对象NO.1考虑用静态工厂方法代替构造函数静态工厂方法好处:(1)构造函数有命名的限制,而静态工厂方法有自己的名字,更加易于理解。(2)静态工厂方法不必在每次调用它们的时候创建一个新的对象。这种做法对于一个要频繁创建相同对象的程序来说,可以极大的提高性能。它使得一个类可以保证是一个singleton;他使非可
Wesley13 Wesley13
3年前
C#设计模式 —— 工厂模式
。  工厂模式同样是项目中最常用的设计模式,工厂模式中又分为简单工厂,工厂方法,抽象工厂。下面我们由简单的开始逐一介绍。1.简单工厂模式  简单工厂又被称为静态工厂,在设计模式中属于创建型模式。主要解决的问题是封装了实例化的过程,通过传入参数来获不同实例。下面我们举一个项目中可能会用到的例子。  假设我们程序的数据保存在几个不同
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k