对Spring IOC容器的理解与控制反转的理解
控制反转
当我们把web的每个任务都视作对外界请求的服务的响应,有了容器bean以后,我们就可以将业务与被管理的对象的生命周期相隔离,真正实现业务只操心业务的事情,而不管被管理的对象的生死存亡。这句话怎么去理解呢?
业务即我们需要提供的服务,或者我们需要实现的功能,而被管理的对象可以分为方法(接口)和实例化的模型对象两种,下边用两个例子来说明这种所谓的控制反转的逻辑。
- 当被管理的对象是实例化模型的时候:
把我们提供的服务视作做一道菜的过程,那么其中必定要用到砧板和盘子(一种需要被管理的对象):在做菜前把砧板和盘子洗好(对象的申请与初始化init),在做菜后把砧板再次洗好并归位以及吃完菜后把盘子洗好(负责对象的销毁与相关清理工作destroy)看似是一种再正常不过的行为(和我们在家做饭的模式十分相似),但对于一个大饭店来说并不是一种好的模式:作为一个厨师他并不想时时刻刻操心盘子和案板到底在哪里有没有洗干净,因此对于这些几乎每个服务都要用到的对象,我们需要一个强有力的管理者——后厨的小二——当厨师(业务)需要用到相关对象(bean)的时候,我们的小二总是能确保厨师手边有能用的对象。从这个例子我们可以看出,有了小二(spring)以后,厨师和盘子的逻辑关系发生了一些改变:以前是厨师(业务类)控制着盘子(实例对象)的生存状态,变成了现在的厨师向小二(spring)去申请盘子(bean即完全受控的实例对象)——就bean分析二者实现了控制反转。 - 当被管理的对象是方法时
送人去学校是我们的业务,校车(方法)送幼儿园的小孩子们时需要确定每一站小孩子们都到齐了,在到达学校后也要对孩子们的人数进行清点,这也是方法执行前后的相关函数,而校车这个服务也被小孩子控制地死死的;转换思路观察公交送老师去学校的过程:老师们只需要在合适的地点上公交车,而公交车并不关心老师在哪里上车以及要去哪里,相反变成了老师受公交车服务控制(bean),当我们需要用到公交车时,我们只需要站在站台(向spring申请bean),到站后下车,而无需操心这个服务的善后工作,这就实现了方法的控制反转。
Spring 上下文
继续以厨师炒菜为例,厨师告诉小二,我在炒某个菜的时候这个地方需要三个盘子放在这个位置,小二便得知,并准备好盘子保证炒菜的正常进行。
所谓Spring的上下文,就是联系容器与Spring的一个中间介质,告诉Spring每个容器中应该放入哪个对象。最常见的接口就是ApplicationContext,而它最常见的作用就是解析配置文本信息,有了上下文对象,我们就能向容器注册需要Spring管理的对象了。
共有五种不同的上下文信息类:
- AnnotationConfigApplicationContext:从一个或多个基于java的配置类中加载上下文定义,适用于java注解的方式;
- ClassPathXmlApplicationContext:从类路径下的一个或多个xml配置文件中加载上下文定义,适用于xml配置的方式;
- FileSystemXmlApplicationContext:从文件系统下的一个或多个xml配置文件中加载上下文定义,也就是说系统盘符中加载xml配置文件;
- AnnotationConfigWebApplicationContext:专门为web应用准备的,适用于注解方式;
- XmlWebApplicationContext:从web应用下的一个或多个xml配置文件加载上下文定义,适用于xml配置方式。
通过上下文信息,只要将需要管理的对象(Spring中我们都称之问bean)、bean之间的协作关系配置好,然后利用应用上下文对象加载进我们的Spring容器,容器就能为程序提供想要的对象管理服务了。