内容简介:在你学习Spring之前,你肯定听说过“控制反转”、“依赖注入”、“上下文”等名词,伴随着这些名词的,是一些冗长晦涩的解释,这些解释并没有什么显著的错误,但是因为太过抽象导致初学者们无法直观地去理解它们。废话不多说,我们通过举例或者写代码来一步一步理解它们。在一个系统里,可能有多个业务部分,比如用户服务,订单服务,数据服务等等,在代码里,这些服务也许分布在多个类中,可能叫做UserService或者OrderService等等。为了简便,我们假设系统里有A、B、C、D四个类,他们有如下的依赖关系:
在你学习Spring之前,你肯定听说过“控制反转”、“依赖注入”、“上下文”等名词,伴随着这些名词的,是一些冗长晦涩的解释,这些解释并没有什么显著的错误,但是因为太过抽象导致初学者们无法直观地去理解它们。
废话不多说,我们通过举例或者写代码来一步一步理解它们。
在一个系统里,可能有多个业务部分,比如用户服务,订单服务,数据服务等等,在代码里,这些服务也许分布在多个类中,可能叫做UserService或者OrderService等等。为了简便,我们假设系统里有A、B、C、D四个类,他们有如下的依赖关系:
简单来说,D是B的成员,A和B是C的成员。以前Spring这种东西没有出现的时候,你可能手动地去创建ABCD对象,再设置他们的依赖关系,如下图:
上面的代码看起来很简单,也不复杂。问题是当你的系统规模扩大了以后,有上百个对象需要初始化以及设置依赖的时候,复杂度就直线上升了。
为了降低复杂度,减少他们之间的耦合,这个时候我们就需要用上Spring容器了。程序里的对象都可以扔到容器里,对象只需要告诉容器它需要哪些依赖就行,容器自动初始化好并给它。比如上面ABCD那个例子,C告诉容器它需要A和B,B告诉容器它需要D,这样ABCD四个对象都可以扔到容器里了,当你想用C的时候,就从容器里面拿出来,这时候C的成员就已经包含了A和B了(我们目前只讨论单例的情况,就是一个类只有一个对象)。
容器通过“配置”来了解对象之间的依赖关系。
在Spring框架里,ApplicationContext就代表了容器(又叫应用程序上下文),容器里的对象,又叫Bean。配置有两种方式,一种是xml,一种是 Java 配置(或者说代码配置)。早些年的时候,Java Web(SSH)开发为人诟病的,就是臃肿的xml配置,虽然目前Spring仍然支持xml配置和混合配置,不过Spring Boot已经 建议 使用Java配置了。我们来通过一个例子来看看如何使用容器和配置:
图中显示了项目的源码结构、程序的入口、配置以及依赖。
上图写出了ABCD的源码。
配置文件是Config.java,它有一个@Configuration注解,这表明Config类是配置类。它还有另外一个注解@ComponentScan,这个注解表示容器应该去扫描程序的代码,看看那些组件应当被初始化为Bean。哪些类会被初始化为Bean呢?我们看看ABCD的源码,发现他们各自都有注解@Component,这个注解就表示了它所在的类是组件,需要初始化Bean。C和B的成员变量都用@Autowired注解来修饰,这样容器就知道他们都依赖哪些Bean了,ABCD的对象都生成好之后,容器就把D对象赋值给B的成员,把A和B的对象赋值给C的成员。
如果你运行程序,会发现输出的结果是true,也就是C里的A成员不为空。这样你是不是就理解了Spring容器的作用了呢?你的程序不必再在ABCD的外部去设置他们的依赖了,反而只需要在ABCD的类的内部指明依赖就行,这个从外而内的过程就是控制反转(IoC,Inversion of Control),控制权交给了Spring容器,Spring容器也叫IoC容器。你还可能听过依赖注入(DI,Dependency Injection),如果你看网上文章没明白,权当他们是一样的好了。
对于开源库,他们的类肯定没有@Component注解,这样肯定不能通过扫描来加入容器。那就需要写点代码了。Config类中有一个objectMapper方法,返回了一个ObjectMapper对象(ObjectMapper是Jackson的关键类),objectMapper方法有个@Bean注解,表示返回的对象会加入到容器中。ObjectMapper对象可以在objectMapper方法里,进行一些修改呀,配置呀等等。
这个时候ObjectMapper对象还没人用,如果ABCD任何一个类想用,只需要在类中加一个成员 @Autowired ObjectMapper objectmapper;
,Spring容器会自动把ObjectMapper对象赋值到这个成员上。非常方便,尤其是在大项目里,类非常多,一行代码就把你需要的对象拿过来用,简直爽的不行。在实践中,依赖的类常常是个接口,使用者只调用接口就行,至于容器给它哪种实现并不重要,这个逻辑在“配置”里就可以控制。这样,程序的耦合度进一步减小了。
在我们之前 运行第一个Spring Boot应用 的时候,我们曾经添加了一个控制器,他有个@Controller注解,这个注解相当于一个特殊的@Component,只不过@Controller表示当前的组件是用来处理网络请求的。类似的还有,@Service用来表示业务相关的组件,@Repository用来表示数据获取相关的组件。他们都是通过自动扫描放到Spring容器中的。
总结
为了让大家理解Spring容器,本文忽略了很多技术上的细节,比如Bean的命名,比如说@ComponentScan的扫描路径和注解参数,比如声明依赖除了在成员上加@Autowired以外还能通过构造方法或者setter等等。我相信你懂了Spring容器的概念之后,这些都不是什么问题。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 深入理解Spring的容器内事件发布监听机制
- 【Java 容器面试题】谈谈你对HashMap 的理解
- 一线专家:微服务、容器和云原生到底该如何理解?| 视频
- 软件工程入门-轻松理解依赖注入 (DI) 和 IoC 容器
- 如何理解 Laravel 和 ThinkPHP 5 中的服务容器与注入?
- 从零开始入门 K8s | 理解容器运行时接口 CRI
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据结构与算法:python语言实现
迈克尔.·T·古德里奇、罗伯托·塔玛西亚、迈克尔·H·戈德瓦瑟 / 张晓、赵晓南 / 机械工业出版社 / 2018-9 / 109.00元
本书采用Python语言讨论数据结构和算法,详细讲解其设计、分析与实现过程,是一本内容全面且特色鲜明的教材。书中将面向对象视角贯穿始终,充分利用Python语言优美而简洁的特点,强调代码的健壮性和可重用性,关注各种抽象数据类型以及不同算法实现策略的权衡。一起来看看 《数据结构与算法:python语言实现》 这本书的介绍吧!