我是Spring 容器的大管家
wechat:大黄奔跑
关注我,可了解更多有趣的面试相关问题。
我是谁?
上文说到 Spring 所有的 Bean 对象都是交给容器来管理,那容器是如何管理 各个对象的呢?本来带领大家一起探索 Spring 容器中的大管家。
还不熟悉的朋友可以看看上一篇文章——我是大名鼎鼎的 IOC。
针对本文探讨的内容,面试中也多次提及。常见的提问方式有
- Spring 如何管理Bean
- IOC 中 各个 Bean之间如何管理
我的职责
作为容器的 "大管家" ,主要职责当然是负责容器中各个对象 (Bean
) 的一起事物。如果非要加一个限定,主要功能有两个
1、业务对象的构建管理(如何管理人员的离职和入职)
利用 IOC
,具体业务不需要关系依赖的对象是如何被创建的,想获取的时候直接拿即可,这部分只需要放心的交给容器的 大管家 即可。
2、业务对象间的依赖(如果管理容器中各个成员之间的相互关系)
作为管家,需要灵活的处理各个对象之间的关系。比如端茶的小李 需要等烧水的小王处理完了之后,才可以去烧水,而作为管家需要灵活处理这些关系,保证观众老爷要使用的时候,可以方便的获取到。保证每个业务对象在使用的时候可以处于就绪的状态。
大管家的秘密
上文说过,被注入的对象可以通过多种方式(比如构造方法、setter
方法、接口形式)向容器中注入对象。那么大管家是如何准确领悟被注入对象的意图的呢?毕竟计算机也不是一个灵活的人,对吧?
容器的管家需要寻找某种方式记录很多对象之间的依赖关系,目前最直观的想法无非说用某个文本将所有的用户信息、用户相互关系用文字记录下来。比如:
- 可以利用基本的文本记录下来各个对象之间的依赖关系。
可以用 容器中独特发明的描述性比较强的
xml
文本格式记录下来对象信息或者直接交给管家的小弟代为记录,每次想找某个人,直接给小弟打电话,我直接当一个甩手大掌柜
…………
…………
那么在 Spring
庞大的家族如何管理容器中各个对象的呢?
下面提供的是伪代码,目的只是为了尽可能简化容器管家的概念,了解的朋友可能知道,下面说的功能类似于 BeanFactory
或者 ApplicationContext
,但是此刻不便提及,避免及早陷于何为 BeanFactory 的思考。
1. 直接编码方式
Spring中,在容器启动之前,可以通过程序的硬编码 方式将被注入的对象和依赖的对象注解到容器中,提前明确各个对象之间的关系。
IocContainer container = new IocContainer(); // 将对象注册到容器中 container.register(XiaoWang.class, "烧水"); container.register(Xiaoli.class, "端茶"); // 看看小王是干嘛的 String useful = container.get(xiaowang.class);
管家想到了一个稳妥方式,我也别用小本本记录下来了,每天早成到我这儿登记。
所以通过编码,可以让 容器的管家 知道管理的奥秘,管理对象和管理对象间的依赖关系。
2. 文本形式记录
这种方式和我前面讨论的如出一辙,基本上是最容易考虑到的,最常见的有,普通的文本记录(txt?),properties文件,XML文件的功能,都可以用于记录并管理对象的关系。
不过对于 Spring 而言,最常见的属于 XML形式,可以用如下方式记录:
<bean id="xiaowang" class="com.service.PersonService.XiaoWang"> <description>"烧水"</description> </bean> <bean id="xiaoli" class="com.service.PersonService.XiaoLi"> <description>"端茶"</description> </bean>
最后作为容器的管家,每次只需要拿着这份名单,或者名单各个角色的作用即可。
3. 注解形式
这个应该是目前 Spring
、Spring Boot
使用最多的形式。很简单只需要在每个类上通过注解来标注各个对象之间依赖关系即可。
是不是有点类似于管家让每个人胸前贴一个标签,每个人都可以根据对象胸前的标识牌来识别对方的信息。(哦豁,不错,大管家已经具备现代酒店管理知识了)
"大家好,我是小王"
@Service public class XiaoWang { }
"大家好,我是小李"
@Service public class XiaoLi { // 小李依赖小王,如果小王没有烧水,我如何端茶呢? @Autowired private XiaoWang xiaoWang; }
如果对象依赖另一个对象时,可以通过注解的方式将其他对象注入,告诉大管家,我依赖他。
当然,这可以可以用户注入的方式有很多,比如 @Autowired
、比如 @Resource
等,此处先不给大家罗列各种注解的方式,毕竟只是一种形式而已,你是带胸牌还是挂腰牌来表明身份,真的很重要吗?
总结
这里简单介绍了 IOC 容器用于管理各个 Bean 对象的方式,再次提到了容器最重要的作用:对象的构建管理 和 业务对象间的依赖管理。而管理的的方式多种多样,直接编码形式由于编码复杂,代码冗余,目前使用已经不多;xml 形式和注解形式属于萝卜青菜各有所爱的地步,目前 Spring Boot 当道,自然 注解方式用起来最为方便,毕竟 Spring Boot 要做的就是开箱即用,何必又回头写一些复杂的 xml 文件呢。
再头回看看开头标记的面试题:Spring 如何管理 Bean?
相信你已经可以很好的回答了。
当然,本文只是对于容器模式的简单抽象,后续会继续介绍容器两大管家:BeanFactory
和 ApplicationContext
。