Alian解读SpringBoot 2.6.0 源码(六):启动流程分析之创建应用上下文

一、背景

  上一篇我们解读了监听器的解析,本篇主要解读命令行参数解析,首先我们还是先回顾下启动的整体流程。

1.1、run方法整体流程

  接下来的几个方法所在类的具体路径:org.springframework.boot.SpringApplication

	public ConfigurableApplicationContext run(String... args) {
		// 1、记录启动的开始时间(单位纳秒)
		long startTime = System.nanoTime();
		
		// 2、初始化启动上下文、初始化应用上下文
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;

		// 3、设置无头属性:“java.awt.headless”,默认值为:true(没有图形化界面)
		configureHeadlessProperty();

		// 4、获取所有 Spring 运行监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// 发布应用启动事件
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			// 5、初始化默认应用参数类(命令行参数)
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

			// 6、根据运行监听器和应用参数 来准备 Spring 环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			// 配置忽略bean信息
			configureIgnoreBeanInfo(environment);

			// 7、创建 Banner 并打印
			Banner printedBanner = printBanner(environment);

			// 8、创建应用上下文
			context = createApplicationContext();
			// 设置applicationStartup
			context.setApplicationStartup(this.applicationStartup);

			// 9、准备应用上下文
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

			// 10、刷新应用上下文(核心)
			refreshContext(context);

			// 11、应用上下文刷新后置处理
			afterRefresh(context, applicationArguments);

			// 13、时间信息、输出日志记录执行主类名
			Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
			}

			// 14、发布应用上下文启动完成事件
			listeners.started(context, timeTakenToStartup);

			// 15、执行所有 Runner 运行器
			callRunners(context, applicationArguments);
		} catch (Throwable ex) {
			// 运行错误处理
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			// 16、发布应用上下文就绪事件(可以使用了)
			Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
			listeners.ready(context, timeTakenToReady);
		} catch (Throwable ex) {
			// 运行错误处理
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		// 17、返回应用上下文
		return context;
	}

1.2、本文解读范围

  本文主要讲解到创建应用上下文,也就是:

	// 8、创建应用上下文
	context = createApplicationContext();
	// 设置applicationStartup
	context.setApplicationStartup(this.applicationStartup);

二、创建应用上下文

2.1、初始化入口

  此方法所在类的具体路径:org.springframework.boot.SpringApplication

public class SpringApplication {
	// 应用上下文工厂
	private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;

	protected ConfigurableApplicationContext createApplicationContext() {
		return this.applicationContextFactory.create(this.webApplicationType);
	}
}

  此方法所在类的具体路径:org.springframework.boot.ApplicationContextFactory

@FunctionalInterface
public interface ApplicationContextFactory {

	/**
	 * 根据web应用程序类型创建ApplicationContextFactory 的一个默认实现
	 * 
	 * @param webApplicationType web应用程序类型
	 * @return web应用程序类型
	 */
	ApplicationContextFactory DEFAULT = (webApplicationType) -> {
		try {
			switch (webApplicationType) {
			case SERVLET:
				return new AnnotationConfigServletWebServerApplicationContext();
			case REACTIVE:
				return new AnnotationConfigReactiveWebServerApplicationContext();
			default:
				return new AnnotationConfigApplicationContext();
			}
		} catch (Exception ex) {
			throw new IllegalStateException("Unable create a default ApplicationContext instance, "
					+ "you may need a custom ApplicationContextFactory", ex);
		}
	};

	/**
	 * 根据web应用程序类型创建的应用程序上下文ConfigurableApplicationContext
	 * 
	 * @param webApplicationType web应用程序类型
	 * @return web应用程序类型
	 */
	ConfigurableApplicationContext create(WebApplicationType webApplicationType);
}

  ApplicationContextFactory 接口里定义了一个根据web应用程序类型创建的应用程序上下文ConfigurableApplicationContext 的抽象方法,同时也定义了一个根据web应用程序类型创建ApplicationContextFactory 的一个默认实现,相当于就是create方法的实现。从我们之前的文章Alian解读SpringBoot 2.6.0 源码(一):SpringApplication对象创建(Spring工厂加载机制)。知道我们的应用程序类型为SERVLET,所以我们这里返回的对象是AnnotationConfigServletWebServerApplicationContext。我们的代码就结束了?当然不是!!!
  要了解AnnotationConfigServletWebServerApplicationContext的实例化,就得先了解它的类结构,由于整个类图太庞大了,这里又主要是讲初始化,所以我们就仅仅看简单的父类图。
在这里插入图片描述
  由于子类实例化时,会先去对父类进行初始化的操作,所以我们一个个类分析。DefaultResourceLoader的实现类很多,并且在我们讲Alian解读SpringBoot 2.6.0 源码(四):启动流程分析之应用环境准备注册应用程序默认转换器组件已经完成了初始化,大家可以debug下,这里就不多讲了。

2.2、初始化AbstractApplicationContext

  类的具体路径:org.springframework.context.support.AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

	// 工厂中MessageSourc(消息资源) bean的名称
	// 如果未提供任何消息,则将消息解析委托给父级
	public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";

	// 工厂中LifecycleProcessor(生命周期处理器) bean的名称
	// 如果未提供,则使用DefaultLifecycleProcessor
	public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";

	// 工厂中ApplicationEventMulticaster(应用程序事件广播器) bean的名称
	// 如果未提供,则使用默认的SimpleApplicationEventMulticast
	public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

	// 由"spring.spel.ignore"系统属性控制的布尔标志
	// 该属性指示spring忽略SpEL,即不初始化SpEL基础结构,默认值为“false”
	private static final boolean shouldIgnoreSpel = SpringProperties.getFlag("spring.spel.ignore");

	static {
		//饿汉式加载ContextClosedEvent类以避免奇怪的类加载器问题
		//在WebLogic 8.1中关闭应用程序时。(达斯汀·伍兹报道。)
		ContextClosedEvent.class.getName();
	}

	// 日志记录器,可用于子类
	protected final Log logger = LogFactory.getLog(getClass());

	// 此上下文的唯一id(如果有)
	private String id = ObjectUtils.identityToString(this);

	// 显示名称
	private String displayName = ObjectUtils.identityToString(this);

	// 父上下文
	@Nullable
	private ApplicationContext parent;

	// 此上下文使用的环境
	@Nullable
	private ConfigurableEnvironment environment;

	// 刷新时应用的BeanFactory后处理器
	private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();

	// 此上下文启动时的系统时间(毫秒)
	private long startupDate;

	// 标识此上下文当前是否处于活动状态的标志
	private final AtomicBoolean active = new AtomicBoolean();

	// 标识此上下文是否已关闭的标志
	private final AtomicBoolean closed = new AtomicBoolean();

	// “refresh” 和 “destroy” 的同步监视器
	private final Object startupShutdownMonitor = new Object();

	// 对JVM关闭挂钩的引用(如果已注册)。
	@Nullable
	private Thread shutdownHook;

	// 此上下文使用的ResourcePatternResolver
	private ResourcePatternResolver resourcePatternResolver;

	// LifecycleProcessor(生命周期处理器),用于在此上下文中管理bean的生命周期。
	@Nullable
	private LifecycleProcessor lifecycleProcessor;

	// MessageSource我们将委托给此接口的实现
	@Nullable
	private MessageSource messageSource;

	// 事件发布中使用的广播器
	@Nullable
	private ApplicationEventMulticaster applicationEventMulticaster;

	// 应用程序启动度量
	private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;

	// 静态指定的侦听器
	private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();

	// 刷新前注册的本地侦听器
	@Nullable
	private Set<ApplicationListener<?>> earlyApplicationListeners;

	// 在multicaster安装之前发布的ApplicationEvents
	@Nullable
	private Set<ApplicationEvent> earlyApplicationEvents;


	// 创建没有父级的新AbstractApplicationContext
	public AbstractApplicationContext() {
		this.resourcePatternResolver = getResourcePatternResolver();
	}

	// 使用给定的父上下文创建新的AbstractApplicationContext
	public AbstractApplicationContext(@Nullable ApplicationContext parent) {
		this();
		setParent(parent);
	}
}
  • 定义了Log对象,可用于子类
  • 定义了上下文的唯一id(如果有),并且它的名称显示
  • 定义了父上下文ApplicationContext 及上下文使用的环境 ConfigurableEnvironment
  • 定义了刷新时应用的BeanFactoryPostProcessor的 List 集合
  • 定义了上下文启动时的系统时间(毫秒)
  • 定义了标识上下文当前是否处于活动状态的标志 active,1为 true,0为 false
  • 定义了标识上下文是否已关闭的标志 closed,1为 true,0为 false
  • 定义了“refresh”“destroy” 的同步监视器
  • 定义了上下文使用的ResourcePatternResolver
  • 定义了用于在此上下文中管理bean的生命周期的LifecycleProcessor(生命周期处理器),默认使用DefaultLifecycleProcessor
  • 定义了MessageSource将委托给此接口的实现
  • 定义了事件发布中使用的广播器ApplicationEventMulticaster,默认为SimpleApplicationEventMulticast
  • 定义了应用程序启动度量
  • 定义了静态指定的侦听器的Set 集合和刷新前注册的本地侦听器Set 集合
  • 定义了在multicaster安装之前发布的ApplicationEvents
  • 无参构造方法创建没有父级的新AbstractApplicationContext
  • 使用给定的父上下文创建新的AbstractApplicationContext

  触发AbstractApplicationContext的构造方法时:

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
		
	public AbstractApplicationContext() {
		this.resourcePatternResolver = getResourcePatternResolver();
	}

}	

  注意这里调用的不是父类默认的实现,而是调用子类GenericWebApplicationContext 重写的方法

public class GenericWebApplicationContext extends GenericApplicationContext
		implements ConfigurableWebApplicationContext, ThemeSource {
		
	@Override
	protected ResourcePatternResolver getResourcePatternResolver() {
		// 此处this就是AnnotationConfigServletWebServerApplicationContext
		return new ServletContextResourcePatternResolver(this);
	}
}

  子类GenericWebApplicationContext的构造方法又调用ServletContextResourcePatternResolver的构造

public class ServletContextResourcePatternResolver extends PathMatchingResourcePatternResolver {

	public ServletContextResourcePatternResolver(ResourceLoader resourceLoader) {
		super(resourceLoader);
	}
}

  ServletContextResourcePatternResolver的构造方法又调用父类PathMatchingResourcePatternResolver 的构造方法

public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {

	private final ResourceLoader resourceLoader;
	
	public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
		Assert.notNull(resourceLoader, "ResourceLoader must not be null");
		// 最终resourceLoader 就是AnnotationConfigServletWebServerApplicationContext
		this.resourceLoader = resourceLoader;
	}
}

  最终得到的resourceLoader为:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext,从之前的类图我们看到了AnnotationConfigServletWebServerApplicationContext 的父类有DefaultResourceLoader ,而DefaultResourceLoader实现了接口ResourceLoader,这样大家就可以理解AnnotationConfigServletWebServerApplicationContext 也是一个ResourceLoader了吧。

public class DefaultResourceLoader implements ResourceLoader {}

2.3、初始化GenericApplicationContext

  类的具体路径:org.springframework.context.support.GenericApplicationContext

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

	private final DefaultListableBeanFactory beanFactory;

	@Nullable
	private ResourceLoader resourceLoader;

	private boolean customClassLoader = false;

	private final AtomicBoolean refreshed = new AtomicBoolean();

	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}
}
  • 定义了DefaultListableBeanFactory(构造方法中赋值) 和 ResourceLoader
  • 定义了customClassLoader(自定义类加载器) 为false
  • 定义了是否刷新标识refreshed,1为 true,0为 false

触发GenericApplicationContext 的构造方法时,会实例化一个DefaultListableBeanFactory,我们还是先看下DefaultListableBeanFactory的父类图(接口省略)
在这里插入图片描述

2.3.1、初始化SimpleAliasRegistry

  类的具体路径:org.springframework.core.SimpleAliasRegistry

public class SimpleAliasRegistry implements AliasRegistry {

	// Log对象
	protected final Log logger = LogFactory.getLog(getClass());

	// key为别名value为规范名称的Map
	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
}
  • 定义了了Log对象
  • 定义了别名映射,key为别名,value为规范名称
2.3.2、初始化DefaultSingletonBeanRegistry

  类的具体路径:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	// 要保留的被抑制异常的最大数目
	private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;

	// 单例对象的缓存:key为bean名,value为bean实例
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	// 单例工厂的缓存:key为bean名,value为ObjectFactory
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	// 早期单例对象的缓存:key为bean名,value为bean实例
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

	// 已注册的单例集合,按注册顺序包含bean名称
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

	// 当前正在创建的bean的名称的Set集合
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	// 当前从创建检查中排除的bean的名称的Set集合
	private final Set<String> inCreationCheckExclusions =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	// 抑制异常的集合,可用于关联相关原因
	@Nullable
	private Set<Exception> suppressedExceptions;

	// 指示当前是否在单例中的标志
	private boolean singletonsCurrentlyInDestruction = false;

	// 一次性bean实例的映射:key为bean名称,value为一次性实例
	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

	// 包含bean名称之间的映射:key为bean名称,value为bean包含的一组bean名称
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

	// 依赖bean名称之间的映射,key为bean名称,value为依赖bean名称的Set集合
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

	// 依赖bean名称之间的映射:key为bean名称,value为bean依赖项的bean名称的Set集合
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

}
  • 定义了要保留的被抑制异常的最大数目为100
  • 定义了单例对象的缓存singletonObjects :key为bean名,value为bean实例
  • 定义了单例工厂的缓存singletonFactories :key为bean名,value为ObjectFactory
  • 定义了早期单例对象的缓存:key为bean名,value为bean实例
  • 定义了已注册的单例集合registeredSingletons ,按注册顺序包含bean名称
  • 定义了当前正在创建的bean的名称的Set集合singletonsCurrentlyInCreation
  • 定义了当前从创建检查中排除的bean的名称的Set集合inCreationCheckExclusions
  • 定义了抑制异常的集合,可用于关联相关原因suppressedExceptions
  • 定义了当前是否在单例中的标志singletonsCurrentlyInDestruction ,true为在单例中,false为不在单例中
  • 定义了一次性bean实例的映射disposableBeans :key为bean名称,value为一次性实例
  • 定义了包含bean名称之间的映射containedBeanMap :key为bean名称,value为bean包含的一组bean名称
  • 定义了依赖bean名称之间的映射dependentBeanMap,key为bean名称,value为依赖bean名称集
  • 定义了依赖bean名称之间的映射dependenciesForBeanMap,key为bean名称,value为bean依赖项的bean名称集。

  DefaultSingletonBeanRegistry是一个实现了SingletonBeanRegistry的通用注册表,支持注册一次性bean,对于注册表的所有调用者,可以通过bean名称获取,其实该类主要在于BeanFactory的实现,作为分解出单例bean实例的公共管理,需要注意的是:这个类既不参与bean概念定义,也不参与bean实例创建过程

2.3.3、初始化FactoryBeanRegistrySupport

  类的具体路径:org.springframework.beans.factory.support.FactoryBeanRegistrySupport

public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {

	// FactoryBeans创建的单例对象缓存:key为FactoryBean名称,value为对象。
	private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
}
  • 定义了FactoryBeans创建的单例对象缓存
2.3.4、初始化AbstractBeanFactory

  类的具体路径:org.springframework.beans.factory.support.AbstractBeanFactory

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

	// 父bean工厂,用于bean继承支持。
	@Nullable
	private BeanFactory parentBeanFactory;

	// 如有必要,使用ClassLoader解析bean类名。
	@Nullable
	private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

	// 如有必要,使用临时ClassLoader解析bean类名
	@Nullable
	private ClassLoader tempClassLoader;

	// 标识是缓存bean元数据,还是为每次访问重新获取它
	private boolean cacheBeanMetadata = true;

	// bean定义值中表达式的解析策略
	@Nullable
	private BeanExpressionResolver beanExpressionResolver;

	// 使用Spring转换服务代替PropertyEditor。
	@Nullable
	private ConversionService conversionService;

	// 要应用于此工厂bean的自定义PropertyEditorRegistrars 
	private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet<>(4);

	// 要应用于此工厂bean的自定义属性编辑器
	private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>(4);

	// 要使用的自定义类型转换器,覆盖默认的PropertyEditor机制
	@Nullable
	private TypeConverter typeConverter;

	// 应用于注释属性值等的字符串解析程序
	private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();

	// 要应用的BeanPostProcessors
	private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();

	// 预过滤后处理器的缓存
	@Nullable
	private volatile BeanPostProcessorCache beanPostProcessorCache;

	// 作用域映射:key为作用域标识符字符串,value为相应的作用域
	private final Map<String, Scope> scopes = new LinkedHashMap<>(8);

	// 使用SecurityManager运行时使用的安全上下文
	@Nullable
	private SecurityContextProvider securityContextProvider;

	// 合并bean定义:key为bean名称,value为合并的RootBeanDefinition
	private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);

	// 已创建至少一次的bean的名称
	private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));

	// 当前正在创建的bean的名称
	private final ThreadLocal<Object> prototypesCurrentlyInCreation =
			new NamedThreadLocal<>("Prototype beans currently in creation");

	// 应用程序启动度量
	private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;

	public AbstractBeanFactory() {
	}
	
}
  • 定义了父bean工厂BeanFactory、解析bean类名的类加载器和临时类似加载器
  • 定义了标识cacheBeanMetadata, true 为缓存bean元数据,false为每次访问重新获取它,默认是true
  • 定义了bean定义值中表达式的解析策略BeanExpressionResolver
  • 定义了转换服务ConversionService,用来代替PropertyEditor
  • 定义了应用于工厂bean的自定义属性编辑注册器PropertyEditorRegistrars的Set集合
  • 定义了自定义属性编辑器PropertyEditor的Map映射
  • 定义了自定义类型转换器TypeConverter ,覆盖默认的PropertyEditor机制
  • 定义了应用于注释属性值等的字符串解析程序
  • 定义了要应用的BeanPostProcessor的List 集合
  • 定义了预过滤后处理器的缓存BeanPostProcessorCache
  • 定义了作用域映射:key为作用域标识符字符串,value为相应的作用域Scope
  • 定义了使用SecurityManager运行时使用的安全上下文 SecurityContextProvider
  • 定义了映射mergedBeanDefinitions:key为bean名称,value为合并的RootBeanDefinition
  • 定义了已创建至少一次的bean的名称的Set集合alreadyCreated
  • 定义了应用程序启动度量ApplicationStartup

  触发AbstractBeanFactory 的初始化时,什么都没有做

2.3.5、初始化AbstractAutowireCapableBeanFactory

  类的具体路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {

	// 创建bean实例的策略
	private InstantiationStrategy instantiationStrategy;

	// 方法参数名的解析器策略
	@Nullable
	private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

	// 是否自动尝试解析bean之间的循环引用
	private boolean allowCircularReferences = true;

	// 是否在循环引用的情况下注入原始bean实例,即使注射的bean最终被包裹起来
	private boolean allowRawInjectionDespiteWrapping = false;

	// 依赖项检查和autowire时要忽略的依赖项类型,作为类对象:例如,字符串。默认值为“无”
	private final Set<Class<?>> ignoredDependencyTypes = new HashSet<>();

	// 依赖项检查和autowire时要忽略的依赖项接口,作为类对象。默认情况下,仅忽略BeanFactory接口
	private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();

	// 当前创建的bean的名称,用于隐式依赖项注册,从用户指定的Supplier 回调触发的getBean等调用
	private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");

	// 未完成FactoryBean实例的缓存:key为FactoryBean名称,value为BeanWrapper
	private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>();

	// 每个工厂类的候选工厂方法缓存
	private final ConcurrentMap<Class<?>, Method[]> factoryMethodCandidateCache = new ConcurrentHashMap<>();

	// 已筛选PropertyDescriptor的缓存:key为bean类,value为PropertyDescriptor数组
	private final ConcurrentMap<Class<?>, PropertyDescriptor[]> filteredPropertyDescriptorsCache =
			new ConcurrentHashMap<>();

	// 创建新的AbstractAutowireCapableBeanFactory
	public AbstractAutowireCapableBeanFactory() {
		super();
		ignoreDependencyInterface(BeanNameAware.class);
		ignoreDependencyInterface(BeanFactoryAware.class);
		ignoreDependencyInterface(BeanClassLoaderAware.class);
		if (NativeDetector.inNativeImage()) {
			this.instantiationStrategy = new SimpleInstantiationStrategy();
		}
		else {
			this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
		}
	}

	// 使用给定父级创建新的AbstractAutowireCapableBeanFactory
	public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		this();
		setParentBeanFactory(parentBeanFactory);
	}
}
  • 定义了创建bean实例的策略InstantiationStrategy
  • 定义了方法参数名的解析器策略为DefaultParameterNameDiscoverer
  • 定义了自动尝试解析bean之间的循环引用标志allowCircularReferences 为true
  • 定义了在循环引用的情况下注入原始bean实例的标志allowRawInjectionDespiteWrapping 为false
  • 定义了依赖项检查和autowire时要忽略的依赖项类型的Set 集合ignoredDependencyTypes
  • 定义了依赖项检查和autowire时要忽略的依赖项接口的Set集合ignoredDependencyInterfaces,默认情况下,仅忽略BeanFactory接口
  • 定义了当前创建的bean的名称,用于隐式依赖项注册
  • 定义了未完成FactoryBean实例的缓存factoryBeanInstanceCache:key为FactoryBean名称,value为BeanWrapper
  • 定义了每个工厂类的候选工厂方法缓存factoryMethodCandidateCache
  • 定义了已筛选PropertyDescriptor的缓存:key为bean类,value为PropertyDescriptor 数组
2.3.6、初始化DefaultListableBeanFactory

  类的具体路径:org.springframework.beans.factory.support.DefaultListableBeanFactory

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	
	// javax注入提供程序类
	@Nullable
	private static Class<?> javaxInjectProviderClass;

	static {
		try {
			javaxInjectProviderClass =
					ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
		} catch (ClassNotFoundException ex) {
			// JSR-330 API not available - Provider interface simply not supported then.
			javaxInjectProviderClass = null;
		}
	}

	// 序列化工程映射:key为序列化id,value为工厂实例
	private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
			new ConcurrentHashMap<>(8);

	// 此工厂的可序列化Id,用于序列化
	@Nullable
	private String serializationId;

	// 是否允许重新注册具有相同名称的不同定义
	private boolean allowBeanDefinitionOverriding = true;

	// 是否允许即使对于懒加载的 bean也立即加载类
	private boolean allowEagerClassLoading = true;

	// 用于依赖项列表和数组的可选OrderComparator
	@Nullable
	private Comparator<Object> dependencyComparator;

	// 用于检查bean定义是否为autowire候选项的解析器
	private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;

	// 可解析的依赖映射:key为依赖项类型,value为相应的自动注入的值
	private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

	// 从bean定义对象的映射到BeanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

	// 从bean名称映射到合并BeanDefinitionHolder
	private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);

	// 单例和非单例bean名称的映射,key为依赖项类型,value为字符串数组
	private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

	// 仅单例bean名称的映射,key为依赖项类型,value为字符串数组
	private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

	// 按注册顺序的bean定义名称的List列表
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

	// 按注册顺序手动注册的单例名称的列表
	private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);

	// 冻结配置时bean定义名称的缓存数组
	@Nullable
	private volatile String[] frozenBeanDefinitionNames;

	// 是否可以为所有bean缓存bean定义的元数据
	private volatile boolean configurationFrozen;

	// 无参构造,具体实现看章节2.3.5
	public DefaultListableBeanFactory() {
		super();
	}

	// 使用给定的parentBeanFactory创建新的DefaultListableBeanFactory
	public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		super(parentBeanFactory);
	}
}
  • 定义了javax注入提供程序类javax.inject.Provider
  • 定义了允许重新注册具有相同名称的不同定义的标识allowBeanDefinitionOverriding ,默认为true
  • 定义了是否允许即使对于懒加载的 bean也立即加载类的标识allowEagerClassLoading ,默认为true
  • 定义了用于依赖项列表和数组的可选OrderComparator
  • 定义了自动注入候选项的解析器AutowireCandidateResolver
  • 定义了可解析的依赖映射resolvableDependencies :key为依赖项类型,value为相应的自动注入的值
  • 定义了从bean定义对象到BeanDefinition的映射beanDefinitionMap
  • 定义了从bean名称到合并BeanDefinitionHolder的映射mergedBeanDefinitionHolders
  • 定义了单例和非单例bean名称的映射allBeanNamesByType ,key为依赖项类型,value为字符串数组
  • 定义了仅单例bean名称的映射singletonBeanNamesByType ,key为依赖项类型,value为字符串数组
  • 定义了按注册顺序的bean定义名称的List列表beanDefinitionNames
  • 定义了按注册顺序手动注册的单例名称的列表manualSingletonNames
  • 定义了冻结配置时bean定义名称的缓存数组frozenBeanDefinitionNames[]
  • 定义了所有bean缓存bean定义的元数据的标识configurationFrozen

2.4、初始化GenericWebApplicationContext

  类的具体路径:org.springframework.web.context.support.GenericWebApplicationContext

public class GenericWebApplicationContext extends GenericApplicationContext
		implements ConfigurableWebApplicationContext, ThemeSource {
			@Nullable
	private ServletContext servletContext;

	@Nullable
	private ThemeSource themeSource;

	// 调用父类GenericApplicationContext的构造方法,具体见章节2.3
	public GenericWebApplicationContext() {
		super();
	}
}
  • 定义了Servlet上下文
  • 定义了主体资源ThemeSource
      触发GenericWebApplicationContext 的初始化时,会调用父类GenericApplicationContext的构造方法,具体见章节2.3

2.5、初始化ServletWebServerApplicationContext

  类的具体路径:org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext

public class ServletWebServerApplicationContext extends GenericWebApplicationContext
		implements ConfigurableWebServerApplicationContext {

	private static final Log logger = LogFactory.getLog(ServletWebServerApplicationContext.class);

	// 常量值DispatcherServlet bean名称
	public static final String DISPATCHER_SERVLET_NAME = "dispatcherServlet";

	private volatile WebServer webServer;

	private ServletConfig servletConfig;

	private String serverNamespace;

	/**
	 * Create a new {@link ServletWebServerApplicationContext}.
	 */
	public ServletWebServerApplicationContext() {
	}
}
  • 定义了常量值DispatcherServlet的bean名称为"dispatcherServlet"
  • 定义了WebServer对象,包含启动服务和停止服务,还有获取端口等,常见的有Tomcat、Jetty、Netty
  • 定义了ServletConfig对象,可以获取servlet实例的名称,上下文访问路径,初始化参数
  • 定义了服务命名空间serverNamespace

  触发ServletWebServerApplicationContext 的初始化时,什么都没有做

2.6、初始化AnnotationConfigServletWebServerApplicationContext

  类的具体路径:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext

public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
		implements AnnotationConfigRegistry {

	private final AnnotatedBeanDefinitionReader reader;

	private final ClassPathBeanDefinitionScanner scanner;

	private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();

	private String[] basePackages;

	// 创建新的AnnotationConfigServletWebServerApplicationContext
	public AnnotationConfigServletWebServerApplicationContext() {
		// 初始化带注解的Bean定义读取器
		this.reader = new AnnotatedBeanDefinitionReader(this);
		// 初始化类路径Bean定义扫描器
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
}
  • 定义了AnnotatedBeanDefinitionReader 构造方法里赋值)
  • 定义了ClassPathBeanDefinitionScanner(构造方法里赋值)
  • 定义了注解类的Set 集合annotatedClasses
  • 定义了字符串数组basePackages[]
2.6.1、实例化AnnotatedBeanDefinitionReader

  类的具体路径:org.springframework.context.annotation.AnnotatedBeanDefinitionReader

public class AnnotatedBeanDefinitionReader {

	private final BeanDefinitionRegistry registry;

	private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;

	private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

	private ConditionEvaluator conditionEvaluator;

	// 为给定注册表创建一个新的AnnotatedBeanDefinitionReader,
	// 如果注册表是EnvironmentCapable,比如ApplicationContext,Environment将被继承,
	// 否则将创建一个新的创建并使用StandardEnvironment
	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
	}

	// 为给定注册表和环境配置创建一个新的AnnotatedBeanDefinitionReader
	// 以BeanDefinitionRegistry的形式将bean定义加载到的BeanFactory
	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		// 注册注配置处理器
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}
}
  • 定义了bean定的注册表BeanDefinitionRegistry
  • 定义了Bean名称生成器AnnotationBeanNameGenerator
  • 定义了作用域元数据解析器AnnotationScopeMetadataResolver
  • 定义了条件评估器ConditionEvaluator

  当触发AnnotationConfigServletWebServerApplicationContext的构造方法时,会获取环境配置,实例化条件评估器,它主要提供推断BeanFactory,推断Environment,推断ResourceLoader,推断ClassLoader等功能,然后注册注释配置处理器,主要是如下结果:

BeanDefinitionHolder说明
org.springframework.context.annotation.ConfigurationClassPostProcessor配置类后处理器
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor自动注入注解Bean后处理器
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor公共注解Bean后处理器
org.springframework.context.event.EventListenerMethodProcessor事件侦听器方法处理器
org.springframework.context.event.DefaultEventListenerFactory默认事件侦听器工厂

  从之前的类图我们看到了AnnotationConfigServletWebServerApplicationContext的父类有GenericApplicationContext,而GenericApplicationContext实现了接口BeanDefinitionRegistry,这样大家就可以理解AnnotationConfigServletWebServerApplicationContext也是一个BeanDefinitionRegistry了吧。

2.6.2、实例化ClassPathBeanDefinitionScanner

  类的具体路径:org.springframework.context.annotation.ClassPathBeanDefinitionScanner

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

	private final BeanDefinitionRegistry registry;

	private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();

	@Nullable
	private String[] autowireCandidatePatterns;

	private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;

	private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

	private boolean includeAnnotationConfig = true;

	 // 通过给定的BeanFactory创建一个新的ClassPathBeanDefinitionScanner
	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
		this(registry, true);
	}

	// 为给定的beanFactory创建一个新的ClassPathBeanDefinitionScanner,
	// 如果传入的beanFactory,不仅实现了BeanDefinitionRegistry接口,也实现了ResourceLoader接口,
	// 它将当做默认的ResourceLoader,通常是ApplicationContext的实现,
	// 如果给定的是一个普通的BeanDefinitionRegistry,则默认的是它将当做默认的ResourceLoader是PathMatchingResourcePatternResolver,
	// 如果beanFactory实现了EnvironmentCapable,将会使用到它的环境,否则它就会初始化并使用StandardEnvironment
	// useDefaultFilters表示是否使用默认的注解比如:@Component、@Repository、@Service、@Controller
	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
		this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
	}

	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment) {
		this(registry, useDefaultFilters, environment,
				(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
	}

	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {
		// BeanDefinitionRegistry 不能为空
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		this.registry = registry;
		// 是否使用默认过滤器
		if (useDefaultFilters) {
			// 得到两个AnnotationTypeFilter过滤器,annotationType分别为
			// org.springframework.stereotype.Component、javax.annotation.ManagedBean
			registerDefaultFilters();
		}
		setEnvironment(environment);
		setResourceLoader(resourceLoader);
	}
}

  实例化ClassPathBeanDefinitionScanner时,会通过为给定的beanFactory创建一个新的ClassPathBeanDefinitionScanner,如果传入的beanFactory,不仅实现了BeanDefinitionRegistry接口,也实现了ResourceLoader接口,它将当做默认的ResourceLoader,通常是ApplicationContext的实现;如果给定的是一个普通的BeanDefinitionRegistry,则默认的ResourceLoaderPathMatchingResourcePatternResolver,如果beanFactory实现了EnvironmentCapable,将会使用到它的环境,否则它就会初始化并使用StandardEnvironment

  useDefaultFilters是指是否要包括的默认过滤器,比如@Component@Repository@Service@Controller
registerDefaultFilters()方法将得到两个AnnotationTypeFilter过滤器,annotationType分别为:org.springframework.stereotype.Componentjavax.annotation.ManagedBean

三、设置应用程序启动度量

  此方法所在类的具体路径:org.springframework.boot.SpringApplication

	context.setApplicationStartup(this.applicationStartup);

  applicationStartup定义都差不多是这个

	private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;

  方法最终实际调用为:

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

	private final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
	
	@Override
	public void setApplicationStartup(ApplicationStartup applicationStartup) {
		super.setApplicationStartup(applicationStartup);
		this.beanFactory.setApplicationStartup(applicationStartup);
	}
}

  简单的父类和工厂的赋值,就不增加篇幅了。

结语

  简单的一个创建实际上做了很多重要的初始化,这些都会在刷新上下文时用到,一定要先了解清楚,至少基本的概念要有个轮廓。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值