【Spring Framework】 使用工厂注册实例的三种方式

337 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

【Spring Framework】 使用工厂注册实例的三种方式

前情提要:

在Spring容器中, 需要在xml中配置来注册组件, 根据这些配置信息完成组件(实例)的实例化, 常见的实例化方法可以归纳为两种:

  1. 构造方法实例化
    1. 无参构造:默认, 不需要额外配置
    2. 有参构造:需要在bean标签中配置子标签constructor-arg, 用以提供参数值
  2. 工厂实例化

根据工厂里的生产方法是否是静态方法, 可以将工厂分为两类:

  1. 静态工厂: 调用类的静态方法生产实例
  2. 实例工厂:先实例化工厂, 再用工厂实例的生产方法生产实例

1. 使用静态工厂

先提供一个bean

public class Fruit {  
    public String type;  
  
    public Fruit(String type) {  
        this.type = type;  
    }  
  
    @Override  
    public String toString() {  
        return "Fruit{" +  
                "type='" + type + '\'' +  
                '}';  
    }  
  
    public String getType() {  
        return type;  
    }  
  
    public void setType(String type) {  
        this.type = type;  
    }  
}

再创建一个静态工厂类

public class FruitStaticFactory {  
    public static Fruit create(){  
        return new Fruit("static fruit factory!");  
    }  
}

在xml文件中注册工厂组件, 注意这里的bean标签多了个factory-method属性, 一是用来表明这是用工厂来实例化对象的, 二是该属性值表示用的工厂的哪个生产方法

<bean id="fruitStaticFactory" class="com.linlin.factory.FruitStaticFactory" factory-method="create"/>

2. 使用动态工厂

创建一个实例工厂类

public class FruitInstanceFactory {  
    public Fruit create(){  
        return new Fruit("instance fruit factory!");  
    }  
}

在xml文件中注册组件, 注意这里需要写两个bean标签, 第一个bean标签不含facotry-xxx属性, 是用于创建factory实例的, 第二个bean标签包含, 是用来根据factory实例的生产方法创建bean对象的.

<bean id="fruitInstanceFactory" class="com.linlin.factory.FruitInstanceFactory"/>  
<bean id="fruitInstance" factory-bean="fruitInstanceFactory" factory-method="create"/>

测试spring容器是否正确创建了Fruit的实例化对象

@Test  
public void test2(){  
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(  
            "application.xml");  
    // 不能只写applicationContext.getBean(Fruit.class), 因为此时xml配置中有两个Fruit实例, 用不同的工厂方法创建!  
    Fruit fruit1 = applicationContext.getBean("fruitInstance",Fruit.class);  
    Fruit fruit2 = applicationContext.getBean("fruitStaticFactory",Fruit.class);  
    System.out.println(fruit1);  
    System.out.println(fruit2);  
  
}

3. 使用FactoryBean

创建一个实现FactoryBean接口的工厂类, 重写两个方法:

  • getObject方法: 生产方法, 返回值就是向容器中注册的组件
  • getObjectType方法: 告知spring容器通过FactoryBean注册的组件的类型信息
public class FruitFactoryBean implements FactoryBean<Fruit> {  
    @Override  
    public Fruit getObject() throws Exception {  
        return new Fruit("fruit factory bean created");  
    }  
  
    @Override  
    public Class<?> getObjectType() {  
        return Fruit.class;  
    }  
}

在xml文件中注册组件, 这里没有factory-xxx这样的属性, 因为会spring容器会自动识别facotryBean, 识别的依据应当是因为FactoryBean类实现了FactoryBean接口

<bean id="fruitFactoryBean" class="com.linlin.factory.FruitFactoryBean"/>

测试spring容器是否正确创建了Fruit的实例化对象

@Test  
public void test3(){  
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(  
            "application.xml");  
    Fruit fruit = applicationContext.getBean("fruitFactoryBean", Fruit.class);  
    System.out.println(fruit);  
}