spring的启动流程

242 阅读3分钟

概述

[spring的使用示例](https://github.com/siyuburno/spring-read-demo/tree/master/src/main/java/ioc/container/demo/beanlifecycle),spring的启动过程就是应用上下文的初始化过程。

可通过如下方式创建一个AnnotationConfigApplicationContext的应用上下文对象:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("ioc.container.demo");

将执行下面的构造函数:

	/**
	 * Create a new AnnotationConfigApplicationContext, scanning for components
	 * in the given packages, registering bean definitions for those components,
	 * and automatically refreshing the context.
	 * @param basePackages the packages to scan for component classes
	 */
	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
		scan(basePackages);
		refresh();
	}

可以看到,启动过程分为3个部分:

  1. this()无参构造函数的执行
  2. 扫描BeanDefinition
  3. refresh()刷新应用上下文

画板

解析

this()无参构造函数的执行

this()先执行父类GenericApplicationContext的无参构造函数:
	/**
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

再执行AnnotationConfigApplicationContext的无参构造行数:

	/**
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

this()的整体整体逻辑是:

  1. 初始化DefaultListableBeanFactory作为IOC容器。
  2. 设置AnnotatedBeanDefinitionReader,可读取@Configuration标注类中的bean。
  3. 设置ClassPathBeanDefinitionScanner,可读取指定包中@Component定义的bean。

扫描BeanDefinition

当前情景下会使用ClassPathBeanDefinitionScanner对象来扫描BeanDefinition,最终执行:
	/**
	 * Perform a scan within the specified base packages,
	 * returning the registered bean definitions.
	 * <p>This method does <i>not</i> register an annotation config processor
	 * but rather leaves this up to the caller.
	 * @param basePackages the packages to check for annotated classes
	 * @return set of beans registered if any for tooling registration purposes (never {@code null})
	 */
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
            // 1. 扫描文件作为Resource:读取指定包下所有的.java文件作为资源。
        	// 2. 将Resource解析成BeanDefinition:判断资源是否被@Component标注,如果是则解析资源。
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
                    // 将BeanDefinition注册到BeanFactory。
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

  1. 扫描文件作为Resource:读取指定包下所有的.java文件作为资源。
  2. 将Resource解析成BeanDefinition:判断资源是否被@Component标注,如果是则解析资源。
  3. 将BeanDefinition注册到Beanfactory。

refresh()刷新应用上下文

refresh()的逻辑定义在父类AbstractApplicationContext中:
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
            // 1 预备应用上下文
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
            // 2.1 预备BeanFactory:设置refreshed=true,设置BeanFactory的id
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
            // 2.2 预备BeanFactory:设置各种各样的BeanFactory的属性值
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
                // 3 预处理BeanFactory,留给子类实现自定义逻辑
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
                // 4 执行PostBeanFactoryProcessor
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
                // 5 注册BeanPostProcessor
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
                // 6 初始化国际化(MassageSource)
				initMessageSource();

				// Initialize event multicaster for this context.
                // 7 初始化应用事件广播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
                // 8 执行onRefresh方法,留给子类实现自定义逻辑
				onRefresh();

				// Check for listener beans and register them.
                // 9 注册监听器,发布前置事件
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
                // 10 注册所有非懒加载的bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
                // 11 发布ContextRefreshedEvent事件。
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

  1. 预备应用上下文
    1. 初始化状态位人:closed=false、active=true;
    2. 创建Environment对象,校验其配置。
    3. 加载内置监听器(ApplicationListener)
    4. 初始化内置事件的列表(ApplicationEvent)
  2. 预备BeanFactory
    1. 设置refreshed=true,设置BeanFactory的id
    2. 设置各种各样的BeanFactory的属性值。
  3. 预处理BeanFactory,留给子类实现自定义逻辑
  4. 执行BeanFactoryPostProcessor
  5. 注册BeanPostProcessor
  6. 初始化国际化MessageSource
  7. 初始化应用事件广播器
  8. 执行onRefresh方法,留给子类实现自定义逻辑
  9. 注册监听器的bean,发布前置事件。
  10. 注册所有非懒加载的bean。
  11. 发布ContextRefreshedEvent事件。