Spring 最重要的概念是 IOC 和 AOP,本文采用的源码版本是 5.2.8.RELEASE
为了降低难度,本文所说的所有的内容都是基于 xml 的配置的方式,实际使用已经很少人这么做了,至少不是纯 xml 配置,不过从理解源码的角度来看用这种方式来说无疑是最合适的。
IOC 总体来说有两处地方最重要,一个是创建 Bean 容器,一个是初始化 Bean。
看下最基本的启动 Spring 容器的例子(利用配置文件)
然后把 Spring 的所有相关的东西都加进来的方式,注意注解
说明:spring-context 会自动将 spring-aop、spring-beans、spring-context、spring-core、spring-expression 这几个基础 jar 包带进来。
Spring 是渐进式的工具,并不具有很强的侵入性,它的模块也划分得很合理,即使你的应用不是 web 应用,或者之前完全没有使用到 Spring,而你就想用 Spring 的依赖注入这个功能,其实完全是可以的,它的引入不会对其他的组件产生冲突
源码分析--UML图:
ApplicationContext context = new ClassPathXmlApplicationContext(...)
就是在 ClassPath 中寻找 xml 配置文件,根据 xml 文件内容来构建 ApplicationContext。当然,除了 ClassPathXmlApplicationContext 以外,我们也还有其他构建 ApplicationContext 的方案可供选择,我们先来看看大体的继承结构是怎么样的:
简化之后就是:
如何去找到这个关系呢?模板方法一层一层网上父类找...ConfigurableApplicationContext接口..然后点击实现类
对这个图进行简单的说明一下:
ClassPathXmlApplicationContext 兜兜转转了好久才到 ApplicationContext 接口,同样的,我们也可以使用绿颜色的 FileSystemXmlApplicationContext 和 AnnotationConfigApplicationContext 这两个类
1、FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样。
2、AnnotationConfigApplicationContext 是基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置,是比较简单的方式,大势所趋。
源码分析---AnnotationConfigApplicationContext
1.先写一个接口,然后将接口增加在配置文件中:
说明:ApplicationContext 启动过程中,会负责创建实例 Bean,往各个 Bean 中注入依赖等。
二、BeanFactory
了解源码之前先分析一下
BeanFactory:生产 bean 的工厂,它负责生产和管理各个 bean 实例。ApplicationContext 其实就是一个 BeanFactory
BeanFactory 接口相关的主要的继承结构:
- ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,我们看源码会发现,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。
- ApplicationContext 继承了 HierarchicalBeanFactory,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。
- AutowireCapableBeanFactory 这个名字中的 Autowire 大家都非常熟悉,它就是用来自动装配 Bean 用的,但是仔细看上图,ApplicationContext 并没有继承它,不过不用担心,不使用继承,不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory() 就知道了。
- ConfigurableListableBeanFactory 也是一个特殊的接口,看图,特殊之处在于它继承了第二层所有的三个接口,而 ApplicationContext 没有。
接下来就是 refresh()
,这里简单说下为什么是 refresh(),而不是 init() 这种名字的方法。因为 ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法重建的,refresh() 会将原来的 ApplicationContext 销毁,然后再重新执行一次初始化操作
三、创建 Bean 容器,加载并注册 Bean--obtainFreshBeanFactory()
这个方法是全文最重要的部分之一,这里将会初始化 BeanFactory、加载 Bean、注册 Bean 等等
当然,这步结束后,Bean 并没有完成初始化。这里指的是 Bean 实例并未在这一步生成。
说明:
所以:ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相关的操作其实是委托给这个实例来处理的。
为什么选择实例化 DefaultListableBeanFactory ?有个很重要的接口 ConfigurableListableBeanFactory,它实现了 BeanFactory 下面一层的所有三个接口。
ConfigurableListableBeanFactory 只有一个实现类 DefaultListableBeanFactory,而且实现类 DefaultListableBeanFactory
还通过实现右边的 AbstractAutowireCapableBeanFactory 通吃了右路。所以结论就是,最底下这个家伙 DefaultListableBeanFactory 基本上是最牛的 BeanFactory 了,
这也是为什么这边会使用这个类来实例化的原因。
未完待续。。。。。