一、接口定义 :
public interface FactoryBean<T> {
//获取对象的工厂方法
@Nullable
T getObject() throws Exception;
//对象类型
@Nullable
Class<?> getObjectType();
//是否是单例,这个属性决定了spring是否基于缓存来将它维护成一个单例对象。
default boolean isSingleton() {
return true;
}
}
public interface ObjectFactory<T> {
//获取对象的工厂方法。
T getObject() throws BeansException;
}
通过接口内容来看,两者都是属于工厂模式用来创建对象使用的。
而区别在于
FactoryBean在BeanFacotry的实现中有着特殊的处理,如果一个对象实现了FactoryBean 那么通过它get出来的对象实际是
factoryBean.getObject() 得到的对象,如果想得到FactoryBean必须通过在 '&' + beanName 的方式获取
而ObjectFactory则只是一个普通的对象工厂接口。
在查看AbstractBeanFacotry的doGetBean(..) 部分的源码时,可以看到spring对ObjectFactory的应用之一就是,将创建对象
的步骤封装到ObjectFactory中 交给自定义的Scope来选择是否需要创建对象来灵活的实现scope。
通过这方面简单的对比可以得到:
FactoryBean的着重于自定义创建对象过程,由BeanFactory通过FactoryBean来获取目标对象,而如果是isSingleton返回true的
话spring会利用单例缓存来缓存通过FactoryBean创建的对象。
而ObjectFactory就是一个普通的工厂对象接口,对于spring在doGetBean处的使用时,在于创建对象的过程由框架通过ObjectFactory定义,而
创建的时机交给拓展接口Scope,除此之外ObjectFactory就是一个普通的接口。
此外在将给依赖注入列表注册一个ObjectFactory类型的对象,在注入过程中会调用objectFactory.getObject()来创建目标对象注入进去。
(如beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());)
简单来说就是通过FactoryBean你可以控制对象如何创建,而ObjectFactory借助Scope接口自定义scope你可以控制对象的创建时机。
三、例子:
car.java
public class Car {
private int maxSpeed;
private String brand;
private double price;
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"maxSpeed=" + maxSpeed +
", brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
CarFactoryBean.java
public class CarFactoryBean implements FactoryBean<Car> {
@Override
public Car getObject() throws Exception {
Car car = new Car();
car.setMaxSpeed(260);
car.setBrand("宝马");
car.setPrice(500000);
return car;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="carFactoryBean" class="hong.factoryBean.CarFactoryBean" >
</bean>
</beans>
Test.java
public class Test {
public static void main(String args[]) {
Resource resource = new ClassPathResource("hong/factoryBean/spring-config.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
System.out.println(beanFactory.getBean("carFactoryBean").toString());
System.out.println(beanFactory.getBean("&carFactoryBean").toString());
}
}