FactoryBean是Spring提供的一个接口,通过实现这个接口可以定制实例化bean。
FactoryBean 接口对于 Spring 框架来说占有重要的地位,Spring 自身就提供了 70 多个FactoryBean 的实现。它们隐藏了实例化一些复杂 bean 的细节,给上层应用带来了便利。
Spring为什么使用FactoryBean
一般情况下,Spring 通过反射机制利用 bean 的 class 属性指定实现类来实例化 bean。
在某些情况下,实例化 bean 过程比较复杂,如果按照传统的方式,则需要提供大量的配置信息,配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。
Spring 为此提供了一个 org.Springframework.bean.factory.FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化 bean 的逻辑。
FactoryBean接口
从Spring3.0开始,FactoryBean 开始支持泛型,即接口声明改为 FactoryBean< T> 的形式:
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
- T getObject():返回由 FactoryBean 创建的 bean 实例,如果 isSingleton()返回 true,则该实例会放到 Spring 容器中单实例缓存池中。
- boolean isSingleton():返回由 FactoryBean 创建的 bean 实例的作用域是 singleton 还是prototype。
- Class getObjectType():返回 FactoryBean 创建的 bean 类型。
当配置文件中< bean>的 class 属性配置的实现类是 FactoryBean 时,通过 getBean()方法返回的不是 FactoryBean 本身,而是 FactoryBean#getObject() 方法所返回的对象。相当于FactoryBean#getObject()代理了 getBean()方法。
FactoryBean案例演示
定义POJO
import lombok.Data;
@Data
public class Car {
private String color;
private String maxSpeed;
private String price;
@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", maxSpeed='" + maxSpeed + '\'' +
", price='" + price + '\'' +
'}';
}
}
实现FactoryBean
import org.springframework.beans.factory.FactoryBean;
/**
* @description: 通过逗号分隔符的方式一次性为Car的所有属性指定配置值。
*/
public class CarFactoryBean implements FactoryBean<Car> {
private String carInfo;
@Override
public Car getObject() throws Exception {
Car car = new Car();
String[] infoArr = carInfo.split(",");
car.setColor(infoArr[0]);
car.setPrice(infoArr[1]);
car.setMaxSpeed(infoArr[2]);
return car;
}
@Override
public Class<Car> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return false;
}
/**
* 功能描述:给carInfo属性注入指定值。(xml方式注入值)
*
* @param carInfo 值
*/
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
}
配置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="com.harvey.CarFactoryBean" >
<property name="carInfo" value="红色,100,200"/>
</bean>
</beans>
测试类
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class FactoryBeanTest {
@Test
public void test () {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/cms/factorybean/car.xml");
// 1.当调用 getBean("car")时,Spring 通过反射机制发现 CarFactoryBean 实现了 FactoryBean的接口,这时 Spring 容器就调用接口方法 CarFactoryBean#getObject()方法返回。
Car car = (Car) context.getBean("car");
// 输出:Car{color='红色', maxSpeed='200', price='100'}
System.out.println(car);
//2.如果希望获取CarFactoryBean 的实例,则需要在使用 getBean(beanName)方法时在 beanName 前显示的加上"&”前缀,例如 getBean("&car")。
CarFactoryBean carFactoryBean = (CarFactoryBean)context.getBean("&car");
// 输出:com.cms.factorybean.CarFactoryBean@7748410a
System.out.println(carFactoryBean.toString());
}
}
源码分析
标签:Spring,接口,bean,FactoryBean,Car,public,car From: https://www.cnblogs.com/xfeiyun/p/17892265.html