Spring
最重要的概念是 IOC
和 AOP
,我将用几篇文章带领大家来分析下 Spring
的 IOC容器
和 AOP
。既然大家平时都要用到 Spring
,怎么可以不好好了解 Spring
呢?阅读这些文并不能让你成为Spring专家,不过一定有助于大家理解Spring的很多概念,帮助大家排查应用中和Spring相关的一些问题。为了降低难度,所有的内容都是基于 xml
的配置的方式。
阅读建议:读者至少需要知道怎么配置 Spring,了解 Spring 中的各种概念,少部分内容我还假设读者使用过 SpringMVC。对于 IOC
总体来说有两处地方最重要,创建 Bean 容器
和初始化 Bean
。
引言
先看下最基本的启动 Spring 容器的例子:
1 | public static void main(String[] args) { |
以上代码就可以利用配置文件来启动一个 Spring
容器了,请使用 maven
的小伙伴直接在 dependencies
中加上以下依赖即可,个人比较反对那些不知道要添加什么依赖,然后把 Spring 的所有相关的东西都加进来的方式。
1 | <dependency> |
spring-context
会自动将spring-core
、spring-beans
、spring-aop
、spring-expression
这几个基础jar
包带进来。
ApplicationContext context = new ClassPathXmlApplicationContext(…) 其实很好理解,从名字上就可以猜出一二,就是在 ClassPath
中寻找 xml
配置文件,根据 xml
文件内容来构建 ApplicationContext
。当然,除了 ClassPathXmlApplicationContext
以外,我们也还有其他构建 ApplicationContext
的方案可供选择,我们先来看看大体的继承结构是怎么样的:
读者可以大致看一下类名,源码分析的时候不至于找不着哪个类,因为 Spring 为了适应各种使用场景,提供的各个接口都可能有很多的实现类。对于我们来说,就是揪着一个完整的分支看完。当然,读本文的时候读者也不必太担心,每个代码块分析的时候,我都会告诉读者我们在说哪个类第几行。
我们可以看到,ClassPathXmlApplicationContext
兜兜转转了好久才到 ApplicationContext
接口,同样的,我们也可以使用绿颜色的 FileSystemXmlApplicationContext
和 AnnotationConfigApplicationContext
这两个类。
FileSystemXmlApplicationContext
的构造函数需要一个 xml
配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext
基本上一样。
AnnotationConfigApplicationContext
是基于注解来使用的,它不需要配置文件,采用 java
配置类和各种注解来配置,是比较简单的方式,也是大势所趋吧。不过本文旨在帮助大家理解整个构建流程,所以决定使用 ClassPathXmlApplicationContext
进行分析。我们先来一个简单的例子来看看怎么实例化ApplicationContext
。
首先,定义一个接口:
1 | public interface MessageService { |
定义接口实现类:
1 | public class MessageServiceImpl implements MessageService { |
接下来,我们在 resources
目录新建一个配置文件,文件名随意,通常叫 application.xml
或 application-xxx.xml
就可以了:
1 |
|
这样,我们就可以跑起来了:
1 | public class App { |
以上例子很简单,不过也够引出主题了,就是怎么样通过配置文件来启动 Spring 的 ApplicationContext?也就是我们随后要分析的 IOC 的核心了。ApplicationContext 启动过程中,会负责创建实例 Bean,往各个 Bean 中注入依赖等。
BeanFactory简介
BeanFactory 从名字上也很好理解,生产 bean 的工厂,它负责生产和管理各个 bean 实例。
初学者可别以为我之前说那么多和 BeanFactory 无关,前面说的 ApplicationContext 其实就是一个 BeanFactory。我们来看下和 BeanFactory 接口相关的主要的继承结构:
我想,大家看完这个图以后,可能就不是很开心了。ApplicationContext
往下的继承结构前面一张图说过了,这里就不重复了。这张图呢,背下来肯定是不需要的,有几个重点和大家说明下就好。
ApplicationContext
继承了ListableBeanFactory
,这个Listable
的意思就是,通过这个接口,我们可以获取多个Bean
,大家看源码会发现,最顶层BeanFactory
接口的方法都是获取单个 Bean 的。ApplicationContext
继承了HierarchicalBeanFactory
,Hierarchical
单词本身已经能说明问题了,也就是说我们可以在应用中起多个BeanFactory
,然后可以将各个BeanFactory
设置为父子关系。AutowireCapableBeanFactory
这个名字中的Autowire
大家都非常熟悉,它就是用来自动装配Bean
用的,但是仔细看上图,ApplicationContext
并没有继承它,不过不用担心,不使用继承,不代表不可以使用组合,如果你看到ApplicationContext
接口定义中的最后一个方法getAutowireCapableBeanFactory()
就知道了。ConfigurableListableBeanFactory
也是一个特殊的接口,看图,特殊之处在于它继承了第二层所有的三个接口,而ApplicationContext
没有。这点之后会用到。
请读者打开编辑器,翻一下 BeanFactory
、ListableBeanFactory
、HierarchicalBeanFactory
、AutowireCapableBeanFactory
、ApplicationContext
这几个接口的代码,大概看一下各个接口中的方法,大家心里要有底,限于篇幅,我就不贴代码介绍了。