Spring 静态工厂与实例工厂

1. 静态工厂创建Bean

1
2
3
4
5
@Data
public class Car {
private String name;
private Double price;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/** 静态工厂类 */
public class CarStaticFactory {
/** 无参 */
public static Car getCar1() {
System.out.println("static Car getCar1()");
Car car = new Car();
car.setName("car1");
car.setPrice(3.14);
return car;
}
/** 有参 */
public static Car getCar2(String name, Double price) {
System.out.println("static Car getCar2()");
Car car = new Car();
car.setName(name);
car.setPrice(price);
return car;
}
}
1
2
3
4
5
6
7
8
9
<bean id="car1" class="bean.CarStaticFactory"
factory-method="getCar1" />

<bean id="car2" class="bean.CarStaticFactory"
factory-method="getCar2">
<!-- 传入参数 -->
<constructor-arg name="name" value="benz"/>
<constructor-arg name="price" value="500.0"/>
</bean>
1
2
3
4
5
6
7
8
@Test
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car1 = (Car) ioc.getBean("car1");
Car car2 = (Car) ioc.getBean("car2");
System.out.println(car1);
System.out.println(car2);
}

运行。可知通过静态工厂类创建Bean的原理是:直接调用静态方法

  • 调用CarStaticFactory.getCart1()
  • 调用CarStaticFactory.getCart2(name, price)

2. 实例工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class CarInstanceFactory {
/** 无参 */
public Car getCar1() {
System.out.println("Car getCar1()");
Car car = new Car();
car.setName("car1");
car.setPrice(3.14);
return car;
}
/** 有参 */
public Car getCar2(String name, Double price) {
System.out.println("Car getCar2()");
Car car = new Car();
car.setName(name);
car.setPrice(price);
return car;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 先注册实例工厂类 -->
<bean id="carInstanceFactory" class="bean.CarInstanceFactory" />

<!-- factory-bean指定工厂类对应的Bean组件 -->
<bean id="car1" factory-bean="carInstanceFactory"
factory-method="getCar1" />

<bean id="car2" factory-bean="carInstanceFactory"
factory-method="getCar2">
<constructor-arg name="name" value="benz" />
<constructor-arg name="price" value="500.0" />
</bean>
1
2
3
4
5
6
7
8
@Test
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car1 = (Car) ioc.getBean("car1");
Car car2 = (Car) ioc.getBean("car2");
System.out.println(car1);
System.out.println(car2);
}

运行。可知通过实例工厂类创建Bean的原理是:

  • 先注册实例工厂类到IOC容器,即IOC容器创建时,会先创建一个工厂类实例
  • 有了工厂类实例之后,会调用工厂方法,创建对应的Bean

3. FactoryBean工厂接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package bean;

import org.springframework.beans.factory.FactoryBean;

public class CarFactoryBeanImpl implements FactoryBean<Car>{
/** 工厂方法,返回要创建的对象 */
@Override
public Car getObject() throws Exception {
System.out.println("getObject()");
Car car = new Car();
car.setName("benz");
car.setPrice(300.0);
return car;
}
/** 返回创建的对象的类型 */
@Override
public Class<?> getObjectType() {
return Car.class;
}
/** 创建的对象是单例还是多例 */
@Override
public boolean isSingleton() {
return true;
}
}
1
<bean id="carFactoryBeanImpl" class="bean.CarFactoryBeanImpl"/>
1
2
3
4
5
6
7
@Test
public void test() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
// 取出的不是工厂类,而是工厂创建的Bean
Car car = (Car) ioc.getBean("carFactoryBeanImpl");
System.out.println(car);
}

3.1. 单例与多例

实现FactoryBean接口时,isSingleton() 决定了对象是单例还是多例

1
2
3
4
5
/** 创建的对象是单例还是多例 */
@Override
public boolean isSingleton() {
return true;
}

运行测试方法,可知单例模式下,从工厂中取出的是同一对象。但是与scope="singleton" 不同之处在于,只有你去取对象时,才会被实例化

1
2
3
4
5
6
7
8
9
10
@Test
public void test() throws Exception {
// 在ioc创建时,car没有被实例化
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
// 在第1次获取Bean时,car才被实例化
Car car1 = (Car) ioc.getBean("carFactoryBeanImpl");
Car car2 = (Car) ioc.getBean("carFactoryBeanImpl");
// true
System.out.println(car1 == car2);
}

修改为多例

1
2
3
4
@Override
public boolean isSingleton() {
return false;
}

1
2
3
4
5
6
7
8
9
10
@Test
public void test() throws Exception {
// 在ioc创建时,car没有被实例化
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
// 每一次获取时,都会实例化新的car
Car car1 = (Car) ioc.getBean("carFactoryBeanImpl");
Car car2 = (Car) ioc.getBean("carFactoryBeanImpl");
// false
System.out.println(car1 == car2);
}
panchaoxin wechat
关注我的公众号
支持一下