1:有什么用
正常我们创建bean的时候都是使用配置的方式,配置后由spring来统一加载创建放到IOC容器中,比如只是简单的通过构造函数,通过setter方法等创建,并且相关的参数的值也都是确定的,此时使用配置的方式无疑是最好的选择,但是如果是bean创建没有那么简单,比如创建对象依赖的数据需要经过复杂的解析,配置的方式就无法实现了,这个时候就可以考虑使用FactoryBean来完成对象的创建了。
2:如何用
为了让我们使用FactoryBean,spring定义了接口org.springframework.beans.factory.FactoryBean
,源码如下:
public interface FactoryBean<T> {
// 获取目标对象,在该方法中创建自定制的对象,并返回
// 我们再getBean时如果传入的bean名称不是&开头的则会调用
// 该方法获取目标对象
@Nullable
T getObject() throws Exception;
// getObject方法返回的对象的类型
@Nullable
Class<?> getObjectType();
// 是否是单例的,默认是true,即为单例
default boolean isSingleton() {
return true;
}
}
我们想要使用的话只需要创建一个类,来实现接口,然后在getObject
方法中创建自己的对象并返回,然后像普通bean一样注册在spring的配置文件中就可以了,注册完毕后,当getBean时如果直接通过bean名称获取,默认就是调用getObject方法获取真实的对象,如果是想要获取bean工厂本身的话,只需要在bean名称前加上&
号就可以了,下面我们来看个例子。
3:例子
3.1:定义要自己创建的对象
public class Car {
private int maxSpeed;
private String brand;
private double price;
...getter setter tostring...
}
3.2:定义工厂bean
public class CarFactoryBean implements FactoryBean<Car> {
// 作为创建目标对象的数据源
private String carInfo;
/**
* 获取对象
*
* @return 自己定制创建的对象
* @throws Exception
*/
@Override
public Car getObject() throws Exception {
Car car = new Car();
String[] infos = carInfo.split(",");
car.setBrand(infos[0]);
car.setMaxSpeed(Integer.valueOf(infos[1]));
car.setPrice(Double.valueOf(infos[2]));
return car;
}
/**
* 返回对象的类型
*
* @return
*/
@Override
public Class<?> getObjectType() {
return Car.class;
}
public String getCarInfo() {
return carInfo;
}
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
}
3.3:定义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="car" class="yudaosourcecode.factorybean.CarFactoryBean">
<property name="carInfo" value="超级跑车,400,2000000"/>
</bean>
</beans>
3.4:测试
@Test
public void testFactoryBean() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("tsetfactorybean.xml");
System.out.println("获取bean工厂本身");
System.out.println(ac.getBean("&car"));
System.out.println("获取内部对象");
System.out.println(ac.getBean("car"));
}
运行:
获取bean工厂本身
yudaosourcecode.factorybean.CarFactoryBean@1fc2b765
获取内部对象
Car{maxSpeed=400, brand='超级跑车', price=2000000.0}
Process finished with exit code 0