Spring IOC 容器源码分析(了解模板方法--钩子方法在spring中的使用)

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 接口相关的主要的继承结构:

  1. ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,我们看源码会发现,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。
  2. ApplicationContext 继承了 HierarchicalBeanFactory,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。
  3. AutowireCapableBeanFactory 这个名字中的 Autowire 大家都非常熟悉,它就是用来自动装配 Bean 用的,但是仔细看上图,ApplicationContext 并没有继承它,不过不用担心,不使用继承,不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory() 就知道了。
  4. 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 了,

这也是为什么这边会使用这个类来实例化的原因。

未完待续。。。。。

 

 

 

原文地址:https://www.cnblogs.com/lq-93/p/13992120.html