BeanFactory 是字面意思是“Bean 工厂”,那么顾名思义“Bean 工厂”就是用来生产 Bean 或者是用来存放 Bean 的吗?
实际上 BeanFactory
是一个 Spring IoC 容器
。
那这个“Bean 工厂”是如何实现的呢?
BeanFactory 接口
这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持,这个容器接口在 org.springframework.beans.factory.BeanFactor 中被定义。
我们实际使用的 “Bean 工厂” 都是 BeanFactory 接口的实现类,例如:
- XmlBeanFactory(用来读取配置文件)
- StaticListableBeanFactory
- DefaultListableBeanFactory
//利用 ClassPathResource() 去加载在路径 CLASSPATH 下可用的 bean 配置文件
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring.xml"));
BeanFactory 代码实现
看完概念可能还是有点懵,不要着急再往下看看。
Animal.java(接口)
public interface Animal {
void eat();
}
Cat.java(实现Animal接口)
public class Cat implements Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
BeanFactory.java(“Bean 工厂”)
import java.util.HashMap;
import java.util.Map;
public class BeanFactory {
private Map<String, Object> beans = new HashMap<>();
public void addBeans(String id, Object bean) {
beans.put(id, bean);
}
public Object getBeans(String id) {
return beans.get(id);
}
}
BeanUtils.java(工具类封装 BeanFactory )
public class BeanUtils {
//静态变量
private static BeanFactory beanFactory =new BeanFactory();
//静态块 只执行一次
//使用静态块实现了 BeanFactory(Spring IoC 容器)在创建的时候就实例化了Bean,而不是在 getBean 时才实例化Bean
static {
beanFactory.addBeans("Animal",new Cat());
}
//静态方法(类调用)
public static Object getBean(String id) {
return beanFactory.getBeans(id);
}
}
Tips:这里为什么要创建BeanUtils
来封装BeanFactory
呢?因为BeanFactory
是一个 Spring IoC 容器
,在 Spring
中容器将创建对象并进行配置管理,而不是我们主动的去 new
一个对象,也是为依赖注入 (DI)
提供支持。
MainTest.java(测试)
public class MainTest {
public static void main(String[] args) {
//使用BeanUtils直接调用静态方法getBean就获取了Bean
Animal animal = (Animal) BeanUtils.getBean("Animal");
animal.eat();
}
}
以上就是对 BeanFactory ( Spring IoC 容器)的简单实现,可以将BeanFactory 理解为一个存放和管理 Bean 的集合(至于 Spring 底层源码使用的是什么集合我不确定,但是肯定比这个简单实现要复杂很多)。
FactoryBean 接口
说完了 BeanFactory,那么疑问又来啦,FactoryBean 又是什么呢?
简单的说,BeanFactory 是 Factory 结尾是工厂;FactoryBean 是Bean 结尾是 Bean实例,但是这个Bean 实现了 FactoryBean
接口。
Bean 分类
Spring 中 Bean分为两种,具体如下:
1. 普通的Bean: < bean id="xxx" class="xxx">
,Spring 直接创建 Bean 实例
2. FactoryBean: FactoryBean 是接口,为IOC容器中Bean的实现提供了更加灵活的方式;是一个特殊的bean,具有工厂生成对象的能力,只能生成特定的对象。Bean必须实现 FactoryBean接口,此接口提供方法 getObject() 用于获得特定bean。
FactoryBean(源码)
public interface FactoryBean<T> {
// 属性名
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
// 获取bean实例,实例化bean 的逻辑就在这里实现
@Nullable
T getObject() throws Exception;
// 获取bean类型
@Nullable
Class<?> getObjectType();
// 是否是单例
default boolean isSingleton() {
return true;
}
}
getObject()
返回 FactoryBean 管理的Bean 实例,并不是FactoryBean 本身的实例。- FactoryBean 管理的对象可以是 singleton (单例)也可以是prototype (非单例),所以此接口有了方法
isSingleton()
返回由FactoryBean 创建的Bean 实例的作用域是singleton还是prototype。 getObjectType()
最主要的目的就是在不创建实例的情况下就能知道想要创建的Bean 实例的类型。
Tips:从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>
的形式。
FactoryBean 与普通的 Bean 区别
FactoryBean不同于普通Bean的是:它是实现了FactoryBean<T>接口
的Bean
,根据该Bean的ID
从BeanFactory
中获取的实际上是 FactoryBean的getObject()返回的特定 Bean 实例
,而不是FactoryBean 本身
,如果要获取FactoryBean对象,需要在Bean id 前加一个 & 符号来获取。