Spring初始化容器源码分析

我的博客

在这里插入图片描述

码云地址带有上篇文章中所用的中文注释和测试类,分支my-test

Spring GitHub地址
码云地址

Spring 是渐进式的工具,并不具有很强的侵入性,它的模块也划分得很合理,即使你的应用不是 web 应用,或者之前完全没有使用到 Spring,而你就想用 Spring 的依赖注入这个功能,其实完全是可以的,它的引入不会对其他的组件产生冲突

ApplicationContext继承结构

构建 ApplicationContext的方案有很多,先来看看大体的继承结构是怎么样的:

在这里插入图片描述

我们可以使用 FileSystemXmlApplicationContextClassPathXmlApplicationContextAnnotationConfigApplicationContext 这三个类来构建 ApplicationContext

1、FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,和 ClassPathXmlApplicationContext 基本上一样。

2、ClassPathXmlApplicationContext 是根据 xml 文件内容来构建 ApplicationContext,就是在 ClassPath 中寻找 xml 配置文件。

3、AnnotationConfigApplicationContext 是基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置,目前主流方式。

BeanFactory继承结构

ApplicationContext 其实就是一个 BeanFactory,生产 bean 的工厂,它负责生产和管理各个 bean 实例,继承结构:

在这里插入图片描述

  1. ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,大家看源码会发现,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。

  2. ApplicationContext 继承了 HierarchicalBeanFactory,Hierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。

  3. AutowireCapableBeanFactory 用来自动装配 Bean 用的,但是仔细看上图,ApplicationContext 并没有继承它,不过不用担心,不使用继承,不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory() 就知道了。

  4. ConfigurableListableBeanFactory 也是一个特殊的接口,看图,特殊之处在于它继承了第二层所有的三个接口,而 ApplicationContext 没有。这点之后会用到。

BeanFactory、ListableBeanFactory、HierarchicalBeanFactory、AutowireCapableBeanFactory、ApplicationContext 这几个接口中的方法:

BeanFactory
ApplicationContext
ListableBeanFactory
AutowireCapableBeanFactory

启动过程分析

public class Test {

    public static void main(String[] args) {
        // 实例化ApplicationContext容器对象
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        context.getBean(Z.class);
    }

}

通过创建AnnotationConfigApplicationContext对象,执行构造方法里的refresh()方法(初始化容器),为什么是 refresh(),而不是 init() 这种名字的方法。因为 ApplicationContext 建立起来以后,其实我们是可以通过调用 refresh() 这个方法重建的,refresh() 会将原来的 ApplicationContext 销毁,然后再重新执行一次初始化操作

在这里插入图片描述

refresh() 方法里面调用的方法很多,一个一个方法来看大概做了些什么事情,首先是prepareRefresh()

在这里插入图片描述

prepareRefresh

这个方法主要是记录启动时间,校验 xml 配置文件,检验environment的properties是否正确,initPropertySources会调用GenericWebApplicationContext的实现,设置容器的环境,初始化容器的属性

在这里插入图片描述

obtainFreshBeanFactory

因为上面调用了GenericApplicationContext的实现,触发构造方法,这里将会创建 BeanFactory,也就是创建了DefaultListableBeanFactory,如下:

	/**
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

obtainFreshBeanFactory方法其实就是拿到之前创建的 beanFactory 对象,spring容器是通过 ConfigurableListableBeanFactory 这个bean工厂进行真正的bean加载。其主要做了三个动作,刷新 beanFactory,获取 beanFactory,返回 beanFactory

	/**
	 * Tell the subclass to refresh the internal bean factory
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 刷新 BeanFactory并指定序列化id
        // 调用了AtomicBoolean的compareAndSet方法,保证只刷新一次
        // 如果再次调用refresh()方法,则会抛出异常
		refreshBeanFactory();
		// 返回刚刚创建的 BeanFactory
		return getBeanFactory();
	}

这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map),这里说的 Bean 还没有初始化,只是配置信息都提取出来了

在这里插入图片描述

prepareBeanFactory

在注册bean之前先给beanFactory配置一些属性,它们可以帮助beanFactory后期去解析、注册其他的bean

在这里插入图片描述

如果上述几个Aware不使用ignoreDependencyInterface会有什么问题呢?如果我们写一个实现类,然后给他默认配置ApplicationContext属性,而这个ApplicationContext是我们自己new的,这就导致了我们使用的不是spring自己生成的ApplicationContext,所以spring为了避免我们手误自己注册下这个属性,而帮我们忽略。

registerResolvableDependency就是当我们使用自动注入比如@AutoWired注入BeanFactory 类型时,他会帮我们注入目前输入的实例对象,而不会去注入他的其他实现类,这是为了避免我们使用其他的自定义的实例对象

在这里插入图片描述

postProcessBeanFactory

Spring中并没有具体去实现postProcessBeanFactory方法,是提供给想要实现BeanPostProcessor的三方框架使用的。谁要使用谁就去实现。其实就是向上下文中添加了一系列的Bean的后置处理器,后置处理器工作的时机是在所有的beanDefinition加载完成之后,bean实例化之前执行。简单来说Bean的后置处理器是用来修改BeanDefinition的属性信息的

在这里插入图片描述

invokeBeanFactoryPostProcessors

实例化和调用所有 BeanFactoryPostProcessor(包括其子类 BeanDefinitionRegistryPostProcessor),在该方法中完成IoC容器的初始化;代码较多,推荐阅读此篇文章

此方法执行完成后,我们自己创建加了注解的Bean会被put到beanDefinitionMap中,上篇文章中有讲

在这里插入图片描述

registerBeanPostProcessors

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		// 获取所有实现BeanPostProcessor接口的bean的名称
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		// 加一是因为方法末尾会注册一个ApplicationListenerDetector接口的实现类
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		// 注册 BeanPostProcessorChecker,用于每个bean的初始化完成后,做一些简单的检查
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		// 缓存实现了priorityOrdered接口的bean
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		// 排序、注册
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		// 缓存实现Ordered接口的bean
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		// 排序、注册
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		// 缓存没有实现两个接口的bean
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		// 注册
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		// 排序注册所有的实现了MergedBeanDefinitionPostProcessor接口的bean
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		// 注册ApplicationListenerDetector,用来检查所有的ApplicationListener
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

这里只是注册,相当于整理所有的BeanPostProcessor,把其提出来,按执行循序放到list中,供后续调用。原来我们只知道所有的BeanPostProcessor都在IoC容器中以bean的形式存在着,但是我们不知道应该如何去执行,以什么顺序去执行。经过该方法解决了该问题

在这里插入图片描述

最后几个方法

        // Initialize message source for this context.
        // 初始化当前 ApplicationContext 的 MessageSource,主要做国际化处理
        initMessageSource();

        // Initialize event multicaster for this context.
        // 初始化当前 ApplicationContext 的事件广播器
        initApplicationEventMulticaster();

        // Initialize other special beans in specific context subclasses.
        // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
        // 空壳方法,类似postProcessBeanFactory()
        onRefresh();

        // Check for listener beans and register them.
        // 注册事件监听器,监听器需要实现 ApplicationListener 接口
        registerListeners();

        // Instantiate all remaining (non-lazy-init) singletons.
        // 初始化所有的 singleton beans,上篇文章已分析
        //(lazy-init 的除外)
        finishBeanFactoryInitialization(beanFactory);

        // Last step: publish corresponding event.
        // 最后,广播事件,ApplicationContext 初始化完成
        finishRefresh();

        // Destroy already created singletons to avoid dangling resources.
        // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
        destroyBeans();

        // Reset 'active' flag.
        // 设置active表示为false
        cancelRefresh(ex);

        // Reset common introspection caches in Spring's core, since we
        // might not ever need metadata for singleton beans anymore...
        // 清除反射的缓存
        // 清除注解的相关缓存
        // 清除classloader缓存
        resetCommonCaches();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值