我们还是来剖析面试题,今天了不起来来带大家看看这个需要看源码的面试题,因为面试的时候,有很多情况不一定需要去看源码就能回答的问题,但是也有很多的问题是需要我们去看源码才能回答的问题,今天我们就来看看一个比较经典的问题,也是关于Spring 的面试题。
BeanFactory
BeanFactory
是 Spring
容器的顶级接⼝,给具体的IOC容器的实现提供了规范。
BeanFactory
只是个接口,并不是IOC容器的具体实现.
而 Spring
的本质是一个 Bean
工厂( BeanFactory )或者说 Bean
容器,它按照我们的要求,生产我们需要的各种各样的 Bean
,提供给我们使用。只是在生产 Bean
的过程中,需要解决 Bean
之间的依赖问题,才引入了依赖注入(DI)这种技术。也就是说依赖注入是 BeanFactory
生产 Bean
时为了解决 Bean
之间的依赖的一种技术而已。
BeanFactory 的实现
Spring
容器给出了很多种实现,如DefaultListableBeanFactory
、XmlBeanFactory
、ApplicationContext
等。而这些具体的容器都是实现了 BeanFactory
,再在其基础之上附加了其他的功能。
DefaultListableBeanFactory
BeanFactory
接口体系的默认实现类,实现以上接口的功能,提供 BeanDefinition
的存储 map
,Bean
对象对象的存储 map
。
其中 Bean
对象实例的存储 map
,定义在 FactoryBeanRegistrySupport
, FactoryBeanRegistrySupport
实现了 SingletonBeanRegistry
接口,而 DefaultListableBeanFactory
的基类 AbstractBeanFactory
,继承于 FactoryBeanRegistrySupport
。
StaticListableBeanFactory
用于存储给定的 bean 对象实例,不支持动态注册功能,是 ListableBeanFactory
接口的简单实现。
ApplicationContext
ApplicationContext
包含 BeanFactory
的所有功能,通常建议⽐ BeanFactory
优先。
ApplicationContext
以⼀种更向⾯向框架的⽅式⼯作以及对上下⽂进⾏分层和实现继承,ApplicationContext
包还提供了以下的功能:
- MessageSource, 提供国际化的消息访问。
- 资源访问,如URL和⽂件
- 事件传播
- 载⼊多个(有继承关系)上下⽂ ,使得每⼀个上下⽂都专注于⼀个特定的层次,⽐如应⽤的web 层;
BeanFactory
提供的⽅法及其简单,仅提供了六种⽅法供客户调⽤:源码如下
String FACTORY_BEAN_PREFIX = "&";
//判断⼯⼚中是否包含给定名称的bean定义,若有则返回true
boolean containsBean(String beanName)
//返回给定名称注册的bean实例。根据bean的配置情况,如果是
singleton模式将返回⼀个共享实例,否则将返回⼀个新建的实例,如果没有找到指定bean,该⽅法
可能会抛出异常
Object getBean(String)
//返回以给定名称注册的bean实例,并转换为给定class类型
Class getType(String name) 返回给定名称的bean的Class,如果没有找到指定的bean实例,则排
除NoSuchBeanDefinitionException异常
Object getBean(String, Class)
//判断给定名称的bean定义是否为单例模式
boolean isSingleton(String)
//返回给定bean名称的所有别名
String[] getAliases(String name)
而 FactoryBean
是干什么用的呢?
FactoryBean
⼀般情况下,Spring
通过反射机制利⽤ <bean>
的 class
属性指定实现类实例化 Bean
,在某些情况下,实例化 Bean
过程⽐较复杂,如果按照传统的⽅式,则需要在 <bean>
中提供⼤量的配置信息。配置⽅式的灵活性是受限的,这时采⽤编码的⽅式可能会得到⼀个简单的⽅案。
Spring
为此提供了⼀个 org.springframework.bean.factory.FactoryBean
的⼯⼚类接⼝,⽤户可以通过实现该接⼝定制实例化Bean的逻辑。FactoryBean
接⼝对于 Spring
框架来说占⽤重要的地位,Spring
⾃身就提供了70多个 FactoryBean
的实现。它们隐藏了实例化⼀些复杂 Bean
的细节,给上层应⽤带来了便利。从 Spring3.0
开始,FactoryBean
开始⽀持泛型,即接⼝声明改为 FactoryBean<T>
的形式
以 Bean
结尾,表示它是⼀个 Bean
,不同于普通 Bean
的是:它是实现了 FactoryBean<T>
接⼝的 Bean
,根据该 Bean
的ID从BeanFactory
中获取的实际上是 FactoryBean
的 getObject()
返回的对象,⽽不是 FactoryBean
本身,如果要获取 FactoryBean
对象,请在id前⾯加⼀个 &
符号来获取。
例如⾃⼰实现⼀个 FactoryBean
,功能:⽤来代理⼀个对象,对该对象的所有⽅法做⼀个拦截,在调⽤前后都输出⼀⾏LOG,模仿 ProxyFactoryBean
的功能。
FactoryBean
⼀个接⼝,当在IOC容器中的 Bean
实现了 FactoryBean
后,通过 getBean(StringBeanName)
获取到的 Bean
对象并不是 FactoryBean
的实现类对象,⽽是这个实现类中的 getObject()
⽅法返回的对象。要想获取 FactoryBean
的实现类,就要getBean(&BeanName)
,在 BeanName
之前加上&
.
在该接⼝中还定义了以下3个⽅法:
代码语言:javascript复制TgetObject():返回由FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中;
booleanisSingleton():返回由FactoryBean创建的Bean实例的作⽤域是singleton还是
prototype;
ClassgetObjectType():返回FactoryBean创建的Bean类型。
总结
BeanFactory
是个 Factory
,也就是IOC容器或对象⼯⼚,FactoryBean
是个 Bean
。在 Spring
中,所有的 Bean
都是由 BeanFactory
(也就是IOC容器)来进⾏管理的。但对 FactoryBean
⽽⾔,这个 Bean
不是简单的 Bean
,⽽是⼀个能⽣产或者修饰对象⽣成的⼯⼚ Bean
,它的实现与设计模式中的⼯⼚模式和修饰器模式类似。