携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
【Spring Framework】 使用工厂注册实例的三种方式
前情提要:
在Spring容器中, 需要在xml中配置来注册组件, 根据这些配置信息完成组件(实例)的实例化, 常见的实例化方法可以归纳为两种:
- 构造方法实例化
- 无参构造:默认, 不需要额外配置
- 有参构造:需要在
bean标签中配置子标签constructor-arg, 用以提供参数值
- 工厂实例化
根据工厂里的生产方法是否是静态方法, 可以将工厂分为两类:
- 静态工厂: 调用类的静态方法生产实例
- 实例工厂:先实例化工厂, 再用工厂实例的生产方法生产实例
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);
}