【架构师面试-Java编程基本功-12】-Spring之IOC与容器

1:控制反转(IOC)有什么作用

管理对象的创建和依赖关系的维护。对象的创建并不是一件简单的事,在对象关系比较复杂时,如果依赖关系需要程序猿来维护的话,那是相当头疼的

解耦,由容器去维护具体的对象

托管了类的产生过程,比如我们需要在类的产生过程中做一些处理,最直接的例子就是代理,如果有容器程序可以把这部分处理交给容器,应用程序则无需去关心类是如何完成代理的

2:IOC 的优点是什么

IOC 或 依赖注入把应用的代码量降到最低。

它使应用容易测试,单元测试不再需要单例和 JNDI 查找机制。

最小的代价和最小的侵入性使松散耦合得以实现。

IOC 容器支持加载服务时的饿汉式初始化和懒加载。

3:Spring IOC 的实现机制

Spring 中的 IOC 的实现原理就是工厂模式加反射机制。

4:Spring 的 IOC 支持哪些功能

Spring 的 IOC 设计支持以下功能:

其中,最重要的就是依赖注入,从 XML 的配置上说,即 ref 标签。对应Spring RuntimeBeanReference 对象。

对于 IOC 来说,最重要的就是容器。容器管理着 Bean 的生命周期,控制着 Bean 的依赖注入。

5:BeanFactory 和 ApplicationContext 有什么区别

BeanFactory 和 ApplicationContext 是 Spring 的两大核心接口,都可以

当做 Spring 的容器。其中 ApplicationContext 是 BeanFactory 的子接口。

依赖关系

BeanFactory:是 Spring 里面最底层的接口,包含了各种 Bean 的定义,读取bean 配置文档,管理 bean 的加载、实例化,控制 bean 的生命周期,维护bean 之间的依赖关系。

ApplicationContext 接口作为 BeanFactory 的派生,除了提供BeanFactory 所具有的功能外,还提供了更完整的框架功能:

继承 MessageSource,因此支持国际化。

统一的资源文件访问方式。

提供在监听器中注册 bean 的事件。

同时加载多个配置文件。

载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一 个特定的层次,比如应用的 web 层。

加载方式

BeanFactroy 采用的是延迟加载形式来注入 Bean 的,即只有在使用到某个 Bean 时(调用 getBean()),才对该 Bean 进行加载实例化。 这样,我们就不能发现一些存在的 Spring 的配置问题。如果 Bean 的某一个属性没有注入,BeanFacotry 加载后,直至第一次使用调用 getBean 方法才会抛出异常。

ApplicationContext,它是在容器启动时,一次性创建了所有的 Bean。这样,在容器启动时,我们就可以发现 Spring 中存在的配置错误,这样有利于检查所依赖属性是否注入。

ApplicationContext 启动后预载入所有的单实例 Bean,通过预载入单实例 bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

相对于基本的 BeanFactory,ApplicationContext 唯一的不足是占用内存空间。

当应用程序配置 Bean 较多时,程序启动较慢。

创建方式

BeanFactory 通常以编程的方式被创建,ApplicationContext 还能以声明的方式创建,如使用 ContextLoader。

注册方式

BeanFactory 和 ApplicationContext 都支持 BeanPostProcessor、BeanFactoryPostProcessor 的使用,但两者之间的区别是:BeanFactory 需要手动注册,而 ApplicationContext 则是自动注册。

6:Spring 设计容器,BeanFactory 和ApplicationContext 的关系

详解

Spring 作者 Rod Johnson 设计了两个接口用以表示容器。

BeanFactory

ApplicationContext

BeanFactory 简单粗暴,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。我们可以称之为 “低级容器”。

ApplicationContext 可以称之为 “高级容器”。因为他比 BeanFactory多了更多的功能。他继承了多个接口。因此具备了更多的功能。例如资源的获取,支持多种消息(例如 JSP tag 的支持),对 BeanFactory 多了工具级别的支持等待。所以你看他的名字,已经不是 BeanFactory 之类的工厂了,而是 “应用上下文”, 代表着整个大容器的所有功能。该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean。

当然,除了这两个大接口,还有其他的辅助接口,这里就不介绍他们了。

BeanFactory 和 ApplicationContext 的关系

为了更直观的展示“低级容器” 和 “高级容器” 的关系,这里通过常用的ClassPathXmlApplicationContext 类来展示整个容器的层级 UML关系。

【架构师面试-Java编程基本功-12】-Spring之IOC与容器

最上面的是 BeanFactory,下面的 3 个绿色的,都是功能扩展接口,这里就不展开。

看下面的隶属 ApplicationContext 粉红色的 “高级容器”,依赖着 “低级容器”,这里说的是依赖,不是继承哦。他依赖着 “低级容器” 的 getBean 功能。而高级容器有更多的功能:支持不同的信息源头,可以访问文件资源,支持应用事件(Observer 模式)。

通常用户看到的就是 “高级容器”。 但 BeanFactory 也非常够用啦!

左边灰色区域的是 “低级容器”, 只负载加载 Bean,获取 Bean。容器其他的高级功能是没有的。例如上图画的 refresh 刷新 Bean 工厂所有配置,生命周期事件回调等。

小结

说了这么多,不知道你有没有理解 Spring IOC? 这里小结一下:IOC 在 Spring 里,只需要低级容器就可以实现,2 个步骤:

1. 加载配置文件,解析成 BeanDefinition 放在 Map 里。

2. 调用 getBean 的时候,从 BeanDefinition 所属的 Map 里,拿出 Class 对象进行实例化,同时,如果有依赖关系,将递归调用 getBean 方法 —— 完成依赖注入。

上面就是 Spring 低级容器(BeanFactory)的 IOC。

至于高级容器 ApplicationContext,他包含了低级容器的功能,当他执行 refresh 模板方法的时候,将刷新整个容器的 Bean。同时其作为高级容器,包含了太多的功能。

一句话,他不仅仅是 IOC。他支持不同信息源头,支持 BeanFactory 工具类,支持层级容器,支持访问文件资源,支持事件发布通知,支持接口回调等等。

7:ApplicationContext 通常的实现是什么

FileSystemXmlApplicationContext :此容器从一个 XML 文件中加载beans 的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。

ClassPathXmlApplicationContext:此容器也从一个 XML 文件中加载beans 的定义,这里,你需要正确设置 classpath 因为这个容器将在classpath 里找 bean 配置。

WebXmlApplicationContext:此容器加载一个 XML 文件,此文件定义了一个 WEB 应用的所有 bean。

如果您觉得文章好看,欢迎点赞收藏,感谢!!☺☻

上一篇:spring入门-注解


下一篇:js的发布订阅模式