你好,我是yes。
继上篇 Spring 开胃菜 之后,这篇我们继续来盘盘 Spring 面试题。
这篇主要介绍几个比较容易混淆的概念,防止被问到的时候一脸懵逼。
比如 BeanFactory 、FactoryBean、ObjectFactory 的区别?等等。
话不多说,发车!

BeanFactory 什么用

BeanFactory 其实就是 IOC 的底层容器
我们都说 Spring 是 IOC 容器,说的再直白点,其实就是 Bean 的工厂,它帮我们生产和管理 Bean,如果我们需要 Bean 就从工厂拿到 bean,所以再来理解下 BeanFactory 这个名字,就知晓它就是 Spring 的核心。
例如我们调用 getBean ,这就是 BeanFactory 定义的方法,通过它得到 Bean。
不过一般我们所述的 BeanFactory 指的是它实现类,例如 DefaultListableBeanFactory。
BeanFactory 本身只是一个接口。

FactoryBean 又是啥

从命名角度来看,我们可以得知它就是一个 Bean,而不是一个工厂。
那为什么名字如此奇怪,它其实是一个接口,并且有以下几个方法
如果一个对象实现了这接口,那它就成为一种特殊的 Bean,注册到 IOC 容器之后,如果调用 getBean 获取得到的其实是 FactoryBean#getObject() 方法返回的结果。
为什么要这样做?
假设你依赖一个第三方的类 A,而我们又不能修改第三方的类,并且这个对象创建比较复杂,那么你就可以创建一个 bean 来封装它:
publicclassAFactoryBeanimplementsFactoryBean<A
{

public A getObject()throws Exception 
{

        A a = 
new
 A();

        a.setXXX

        ....

        ...

return
 A

    }

    ....省略一些实现

}

这样,我们 getBean("A") 会得到 AFactoryBean#getObject 的结果。
如果单纯只想要 AFactoryBean, 那么加个 “&” 即可,即 getBean("&A")

ObjectFactory 又是啥

从命名角度来看,它是一个工厂。
好吧,摊牌了,没啥特殊含义,就是一个工厂。
在前面我写的循环依赖文章里就用到它了,三级缓存的 map 里面存储的就是 ObjectFactory,用于延迟代理对象的创建。
其实就是封装对象的创建过程,像三级缓存里的 ObjectFactory 逻辑就是判断这个 Bean 是否有代理,如果有则返回代理对象,没有则返回原来传入的对象。

ApplicationContext 呢

ApplicationContext 对我们来说应该很熟悉,我们基本上都是基于 ApplicationContext 操作的。
它也实现了 BeanFactory 这个接口,也属于一个 BeanFactory ,但是它内部还包装了一个 BeanFactory 的实现,这属于组合
而关于 Spring Beans 的一些操作都是委托内部的 BeanFactory 来操作的
所以它有 BeanFactory 的所有功能,并且基于此它还扩展了很多其他功能:
  • AOP
  • 国际化
  • 资源管理
  • 事件
  • 注解
  • 等等
因此,我们开发直接用的肯定是 ApplicationContext 而不是 BeanFactory。

Bean 一共有几种作用域

从官网,我们很容易可以得知,最新版本一共有六种作用域:
  • singleton:默认是单例,含义不用解释了吧,一个 IOC 容器内部仅此一个
  • prototype:原型,多实例
  • request:每个请求都会新建一个属于自己的 Bean 实例,这种作用域仅存在 Spring Web 应用中
  • session:一个 http session 中有一个 bean 的实例,这种作用域仅存在 Spring Web 应用中
  • application:整个 ServletContext 生命周期里,只有一个 bean,这种作用域仅存在 Spring Web 应用中
  • websocket:一个 WebSocket 生命周期内一个 bean 实例,这种作用域仅存在 Spring Web 应用中
别背网上那些多年前的答案了,以上才是最新的~

Spring 一共有几种注入方式

  • 构造器注入,Spring 倡导构造函数注入,因为构造器注入返回给客户端使用的时候一定是完整的。
  • setter 注入,可选的注入方式,好处是在有变更的情况下,可以重新注入。
  • 字段注入,就是平日我们用 @Autowired 标记字段
  • 方法注入,就是平日我们用 @Autowired 标记方法
  • 接口回调注入,就是实现 Spring 定义的一些内建接口,例如 BeanFactoryAware,会进行 BeanFactory 的注入
其实官网上关于注入就写了构造器和setter :
像字段注入其实官方是不推荐的使用的。
因为字段注入依赖注解,然后无法注入静态字段,无法控制成员变量注入顺序。
emmmm...怎么说呢,反正我字段注入用的最多,你们呢,哈哈哈。

最后

好了,这篇就到这里,下篇正在写,准备盘盘 Spring AOP 的面试题。
对了,如果你最近面试有遇到什么 Spring 的面试题,可以给我提供题型啊,我会填充答案补上的。
我的个人微信:yes_oba
我是yes,从一点点到亿点点,我们下篇见~
推荐阅读
继续阅读
阅读原文