概述
BeanFactory 和 FactoryBean 从字面意思可以知道:Bean工厂、工厂Bean
ObjectFactory
BeanFactory
以Factory结尾,表示它是一个工厂类(接口),用于管理Bean的一个工厂
在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
负责配置、创建、管理Bean
BeanFactory 本身只是一个接口
BeanFactory作为bean工厂,是spring的基础容器,它可以管理单例bean对象从创建到销毁的整个生命周期。
源码
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> var1);
<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
boolean containsBean(String var1);
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1) throws NoSuch BeanDefinitionException;
@Nullable
Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
}
初始化顺序
- 创建配置文件
- 装载配置文件
- 启动 IoC 容器
- 获取 Bean 实例(getBean())
通过 BeanFactory 启动 IoC 容器时,并不会初始化配置文件当中定义的 Bean,初始化的动作发生在第一次调用某个 Bean 的时候
FactoryBean
以Bean结尾,表示它是一个Bean
不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取
它就是一个 Bean,而不是一个工厂
FactoryBea可以作为BeanFactory管理的bean对象
,同时BeanFactory对FactoryBean会做出特殊处理。如果FactoryBean被定义为spring的bean,则获取该bean时需要在beanName前面加上&符号,否则获取的bean是FactoryBean创建的对象。
源码
public interface FactoryBean<T> {
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
getObject用来返回实例化后的对象
。getObjectType用来返回对象的类型
。isSingleton用来标识对象是否为单例的,这里默认为true,Spring会将实例化后的对象放入BeanFactory容器中
。BeanFactory中获取的并不是这个类本身,而是FactoryBean的getBean()返回的对象
,如果要获取FactoryBean对象,请在id前面加一个&符号来获取:通过转义符&来区分获取FactoryBean产生的对象和FactoryBean对象本身(FactoryBean实现类)
ObjectFactory
只是作为一个普通的对象工厂,也不作为spring管理的bean使用,BeanFactory不会对ObjectFactory做特殊处理。它主要是用作BeanFactory子类的内部类或者使用lambda表达式封装bean的创建过程。
spring对ObjectFactory的应用之一:将创建对象的步骤封装到ObjectFactory中 交给自定义的Scope来选择是否需要创建对象来灵活的实现scope
源码
@FunctionalInterface
public interface ObjectFactory<T> {
T getObject() throws BeansException;
}
获取单例bean及从自定义作用域中获取bean均使用
ObjectFactory调用createBean方法封装了bean的创建。
与BeanFactory区别
- BeanFactory实现了ObjectFactory接口
- ObjectFactory仅仅关注一个或者一种类型Bean的查找,并且自身不具备依赖查找的能力.
- BeanFactory则提供单一类型,集合类型和层次性的依赖查找能力.
用途
这用于延迟查找的场景,当得到 ObjectFactory 对象时,相当于 Bean 没有被创建,只有当 getObject() 方法时,才会触发 Bean 实例化等生命周期
。
主要用于暂时性地获取某个 Bean Holder 对象
,如果过早的加载,可能会引起一些意外的情况,比如当 Bean A 依赖 Bean B 时,如果过早地初始化 A,那么 B 里面的状态可能是中间状态,这时候使用 A 容易导致一些错误
ApplicationContext
ApplicationContext由BeanFactory派生而来;BeanFactory的许多功能需要编程实现,而在ApplicationContext中则可以通过配置的方式实现;
ApplicationContext因此也称之为Spring上下文
。
可以理解成一个包含所有bean的容器,在单例模式下当有其他地方需要使用某一个bean的时候他就取出来注入到那个地方,所有在不同地方采用@Autowired注入的同一个类型的bean都是同一个bean。
源码
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.lang.Nullable;
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
@Nullable
String getId();
String getApplicationName();
String getDisplayName();
long getStartupDate();
@Nullable
ApplicationContext getParent();
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
ApplicationContext.getBean
在@Configuration类中注入ApplicationContext后使用ApplicationContext.getBean(XXX.class)获取到的bean和@Autowired注入的XXX bean都是同一个。因为他们都是来自于同一个容器。
通过ApplicationContext的getBean方法来获取Spring容器中已初始化的bean。getBean一共有以下四种方法原型:参考博客
- getBean(String name):
参数name表示IOC容器中已经实例化的bean的id或者name,且无论是id还是name都要求在IOC容器中是唯一的不能重名。那么这种方法就是通过id或name去查找获取bean
- getBean(Class< T > type):
参数Class<T> type表示要加载的Bean的类型。如果该类型没有继承任何父类(Object类除外)和实现接口的话,那么要求该类型的bean在IOC容器中也必须是唯一的
,getBean(String name)获得的对象需要类型转换而getBean(Class type)获得的对象无需类型转换。 - getBean(String name, Class type):
适合当类型不唯一时,再通过id或者name来获取bean
- getBean(String name, Object[] args):
本质还是通过bean的id或者name来获取bean,通过第二个参数Object[] args可以给bean的属性赋值,赋值的方式有两种:构造方法和工厂方法。但是通过这种方式获取的bean必须把scope属性设置为prototype,也就是非单例模式。
与BeanFactory区别
- ApplicationContext是BeanFactory的子类,并扩展了功能:
BeanFactory是Spring中比较原始的Factory,它不支持AOP、Web等Spring插件,而ApplicationContext不仅包含了BeanFactory的所有功能,还支持Spring的各种插件,还以一种面向框架的方式工作以及对上下文进行分层和实现继承。
- 初始化:
BeanFactory在初始化容器时,并未实例化 Bean
,ApplicationContext在初始化应用上下文时,会实例化所有单实例的 Bean,所以相对来说,占用空间较大、初始化时间会比 BeanFactory 稍长
- 延迟加载:
BeanFactroy只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化
,ApplicationContext在自身初始化的时候,就会一次性创建了所有的Bean
- 手动、自动注册:
BeanFactory需要手动注册,而ApplicationContext则是自动注册
ApplicationContext扩展了很多其他功能:
- AOP
- 国际化
- 资源管理
- 事件
- 注解
- 等等
- 我们开发直接用的肯定是 ApplicationContext 而不是 BeanFactory
结论
BeanFactory就是对象工厂,用于实例化和保存对象。
FactoryBean是一个工厂对象,用于实例化创建过程比较复杂的对象。
ObjectFactory是某个特定的工厂,用于在项目启动时,延迟实例化对象,解决循环依赖问题。
BeanFactory和ObjectFactory
:
- BeanFactory和ObjectFactory都提供依赖查找的能力
BeanFactory实现了ObjectFactory接口
ObjectFactory仅仅关注一个或者一种类型Bean的查找,并且自身不具备依赖查找的能力
.BeanFactory则提供单一类型,集合类型和层次性的依赖查找能力
.
BeanFactory和FactoryBean:FactoryBean的着重于自定义创建对象过程,由BeanFactory通过FactoryBean来获取目标对象,而如果是isSingleton返回true的话,spring会利用单例缓存来缓存通过FactoryBean创建的对象
ObjectFactory和FactoryBean
- 在将
给依赖注入列表注册一个ObjectFactory类型的对象,在注入过程中会调用objectFactory.getObject()来创建目标对象注入进去
- 是一个普通的工厂对象接口,对于spring在doGetBean处的使用时,在于创建对象的过程由框架通过ObjectFactory定义,而创建的时机交给拓展接口Scope
通过FactoryBean你可以控制对象如何创建,而ObjectFactory借助Scope接口自定义scope你可以控制对象的创建时机