Spring中IOC容器初始化过程解析

Posted 踩踩踩从踩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中IOC容器初始化过程解析相关的知识,希望对你有一定的参考价值。

前言

本篇文章主要解析spring框架ioc容器初始过程,包含启动过程中,涉及到的一些类,ApplicationContext继承体系,以及各个部分涉及到的一部分功能,BeanFactory继承体系 对比着之前设计的ioc上差别部分,功能更加全面;本篇文章主要是解析其源码,而不是单纯的记那是那里,而是理解设计思路才是最重要的。

IOC容器初始化过程

Ioc容器是什么,解决了什么问题,这也是spring中很重要得概念。也就是 ApplicationContext  

包括了 用法和工作流程。

IOC 容器,为用户提供创建、管理、获取它们的类实例的容器。让用户在需要类对象时,只需向
IOC 容器要,进而达到与具体类解耦。为其他的高级功能提供基础。

 包括上面得用法 

 Spring的用法

新建一个普通的 java maven 工程,引入 spring ioc jar ,排除其他依赖,只需要一个干净纯粹的
环境。
<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-context</artifactId> 
    <version>5.2.8.RELEASE</version> 
</dependency>
使用 spring 的三种方式: xml 配置、注解、 bean 配置。
public class AnnotationConfig 

	public static void main(String[] args) 
		ApplicationContext context = new AnnotationConfigApplicationContext(
				"edu.dongnao.courseware.spring.bean");
		Boy boy = context.getBean(Lad.class);
		boy.sayLove();
	
@Configuration
@ComponentScan("edu.dongnao.courseware.spring.runner")
public class JavaBaseConfig 
    public MagicGril magicGril() 
        return new MagicGril("magic gril");
    

    public static void main(String[] args) 
        ApplicationContext context = new AnnotationConfigApplicationContext(JavaBaseConfig.class);

        MagicGril gril = context.getBean(MagicGril.class);
        gril.toString();
    

这是在spring中提供给我们 获取bean得方式。

所有的东西在applicationcontext 做了一个整合 如何加载bean定义。

Applicationcontext是什么

在注释上说了,提供了可配置的应用,他是一个在运行时只读的应用,但是可以实现重新加载的子类。

 包括在看 spring中继承的体系中。

 

  • Environment接口
用来表示整个应用运行时的环境,为了更形象地理解 Environment ,你可以把 Spring 应用的运行时
简单地想象成两个部分:一个是 Spring 应用本身,一个是 Spring 应用所处的环境。
除了外部的各种各方面配置文件,还有一个 profile 配置,定义 bean 逻辑组。
  • HierarchicalBeanFactory接口
工厂分层接口, getParentBeanFactory 获得父工厂,只能子读父工厂。 containsLocalBean 本工厂
是否包含某个 bean

 在ApplicationContext中提供的方法,包含了   提供的方法 ,id 应用名称等等。  

 

ApplicationContext的实现体系

  • ConfigurableApplicationContext子接口
可配置的 ApplicationContext 接口,提供了父容器、环境、 BeanFactory 后置处理器、监听器等配
置方法。
提供可获得 ConfigurableListableBeanFactory 接口的方法
实现了 Lifecycle Closeable 接口,意味着能够进行生命周期的控制和关闭操作。

  • AbstractApplicationContext抽象实现类

继承自 DefaultResourceLoader ,默认为 Classpath 资源加载器
进行了大量通用的接口方法实现,包括 ApplicationContext ConfigurableApplicationContext
BeanFactory ListableBeanFactory HierarchicalBeanFactory MessageSource
ResourcePatternResolver Lifecycle 8 个父接口的方法实现。为子类的实现进行了大量减负,遗
refreshBeanFactory closeBeanFactory getBeanFactory 方法给子类实现。
最重要的方法 refresh ApplicationContext 初始化加载过程的呈现通用的xml的,groovyappliction的。

 利用模板方法的设计模式,

这些都是 抽象类  而且 这个公共抽象类中,并没有bean工厂。利用 getbeanfactory方法 去获取bean工厂。

 

  • AbstractRefreshableApplicationContext

 

        自1.1.3 版本提供的抽象实现,提供 bean 工厂刷新方法的实现,可以配置是否允许重写 bean 定义以及循环依赖。AbstractRefreshableConfigApplicationContext 子类则增加了资源配置入口,通过Environment 解析出配置的真实资源路径字符串。
添加配置的属性的方法。

可以配置 资源文件。 添加配置的部分。
        它的子类实现是指定了资源的加载方式,比如XML 资源方式的子类实现:
ClassPathXmlApplicationContext FileSystemXmlApplicationContext

对应不同的子类进行扩展加载的。
 刷新加载 bean定义。可刷新的部分,职责分明。
  • GenericApplicationContext

      它实现了BeanDefinitionRegistry接口,该接口定义了bean定义信息的注册行为。即我们可以直接往GenericApplicationContext中注册bean定义。

        GenericApplicationContext的bean定义注册是不是委托给了持有的

        GenericGroovyApplicationContext groovy方式配置、 GenericXmlApplicationContext 通用
xml 配置、 StaticApplicationContext 静态资源配置方式。

        AnnotationConfigApplicationContex 了解它的构造方法、 register 方法。

        GenericXmlApplicationContext 了解它的构造方法、 load 方法

可以看出 AbstractRefreshableApplicationContext 是继承式逐步扩展, GenericApplicationContext则是组合式扩展。

ApplicationContext接口一共有6个实现类

两种 XML 指定加载方式实现:
        ClassPathXmlApplicationContext 项目下配置文件
       FileSystemXmlApplicationContext 文件系统配置文件
四种通用加载方式实现:
        AnnotationConfigApplicationContext 注解配置
        GenericGroovyApplicationContext groovy方式配置
        GenericXmlApplicationContext 通用的 xml 配置
        StaticApplicationContext 编程方式进行方式配置资源,常用于配置场景

BeanFactory继承体系

BeanFacotryApplicationContext的关系
从前面的源码中分析中得到 BeanFactory 接口在 ApplicationContext 容器中继承体系中,在实现体
系中的 AbstractRefreshableConfigApplicationContext GenericApplicationContext 实现类则持
BeanFactory 接口的 DefaultListableBeanFactory 实例。

 

ApplicationContext BeanFactory 的关系非常简单,持有组合关系,但是 BeanFactory
DefaultListableBeanFactory 的关系就错综复杂了,这里有三条路径从
DefaultListableBeanFactory BeanFactory

 

 一定要探求beanfactory到defaultListableBeanfactory. 

ApplicationContext BeanFactory 的关系非常简单,持有组合关系,但是 BeanFactory
DefaultListableBeanFactory 的关系就错综复杂了,这里有三条路径从
DefaultListableBeanFactory BeanFactory

关键实现类:DefaultListableBeanFactory  

直接的子接口下分了三条路,呈现出三国鼎立之势,各有各的特点: ListableBeanFactory
迭代、 AutowireCapableBeanFactory 可自动注入、 HierarchicalBeanFactory 具有父子关
系。
经过一列演变,最终归而为一, ConfigurableListableBeanFactory 接口继承了三个接口特
点,自成一体。 DefaultListableBeanFactory类就是 ConfigurableListableBeanFactory 接口最终的实现, XmlBeanFactory则在 Spring 3.1 中废除。

StaticListableBeanFactory 用于编程遍历的实现
SimpleJndiBeanFactory 用于 JNDI ,简单的实现自 BeanFactory 接口

@Configuration
@ComponentScan("edu.courseware")
public class Application 
    
    public static void main(String[] args) 
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        Lad cs = context.getBean("swk", Lad.class);
        cs.sayLove();
        
        ApplicationContext context1 = new FileSystemXmlApplicationContext("F:/workspace/idea/vip/spring-source/src/main/resources/application.xml");
        cs = context1.getBean("lad", Lad.class);
        cs.sayLove();
        
        context1 = new GenericXmlApplicationContext("file:F:/workspace/idea/vip/spring-source/src/main/resources/application.xml");
        cs = context1.getBean("swk", Lad.class);
        cs.sayLove();

        // 注解的方式
        ApplicationContext context2 = new AnnotationConfigApplicationContext(Application.class);
        Lad cs2 = context2.getBean(Lad.class);
        cs2.sayLove();

        System.out.println("------------------------------------------------------");
        GenericApplicationContext context3 = new GenericApplicationContext();
        new XmlBeanDefinitionReader(context3).loadBeanDefinitions("classpath:application.xml");
        new ClassPathBeanDefinitionScanner(context3).scan("edu.dongnao.courseware");
        // 一定要刷新
        context3.refresh();
        cs2 = context3.getBean("swk", Lad.class);
        cs2.sayLove();
        MagicGril ab = context3.getBean(MagicGril.class);
        ab.start();
        
        //  用法跟GenericApplicationContext一样
        // ApplicationContext context4 = new StaticApplicationContext();
    

其中最重要的就是Refresh()方法。

其中会做很多 包括 刷新做准备 这在  applicationcontext中会用到的。

 

以上是关于Spring中IOC容器初始化过程解析的主要内容,如果未能解决你的问题,请参考以下文章

Spring IOC源代码具体解释之容器依赖注入

Spring之IOC容器初始化过程

Spring源码剖析1:初探Spring IOC核心流程

Spring中Bean定义加载过程解析

Spring IoC容器初始化过程

Spring框架学习[IoC容器高级特性]