目录

  • 一、背景
    • 1.1、run方法整体流程
    • 1.2、本文解读范围
  • 二、创建应用上下文
    • 2.1、初始化入口
    • 2.2、初始化AbstractApplicationContext
    • 2.3、初始化GenericApplicationContext
      • 2.3.1、初始化SimpleAliasRegistry
      • 2.3.2、初始化DefaultSingletonBeanRegistry
      • 2.3.3、初始化FactoryBeanRegistrySupport
      • 2.3.4、初始化AbstractBeanFactory
      • 2.3.5、初始化AbstractAutowireCapableBeanFactory
      • 2.3.6、初始化DefaultListableBeanFactory
    • 2.4、初始化GenericWebApplicationContext
    • 2.5、初始化ServletWebServerApplicationContext
    • 2.6、初始化AnnotationConfigServletWebServerApplicationContext
      • 2.6.1、实例化AnnotatedBeanDefinitionReader
      • 2.6.2、实例化ClassPathBeanDefinitionScanner
  • 三、设置应用程序启动度量
  • 结语

一、背景

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

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();// 设置applicationStartupcontext.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();// 设置applicationStartupcontext.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 DefaultResourceLoaderimplements ConfigurableApplicationContext {// 工厂中MessageSourc(消息资源) bean的名称// 如果未提供任何消息,则将消息解析委托给父级public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";// 工厂中LifecycleProcessor(生命周期处理器) bean的名称// 如果未提供,则使用DefaultLifecycleProcessorpublic static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";// 工厂中ApplicationEventMulticaster(应用程序事件广播器) bean的名称// 如果未提供,则使用默认的SimpleApplicationEventMulticastpublic 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);// 父上下文@Nullableprivate ApplicationContext parent;// 此上下文使用的环境@Nullableprivate 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关闭挂钩的引用(如果已注册)。@Nullableprivate Thread shutdownHook;// 此上下文使用的ResourcePatternResolverprivate ResourcePatternResolver resourcePatternResolver;// LifecycleProcessor(生命周期处理器),用于在此上下文中管理bean的生命周期。@Nullableprivate LifecycleProcessor lifecycleProcessor;// MessageSource我们将委托给此接口的实现@Nullableprivate MessageSource messageSource;// 事件发布中使用的广播器@Nullableprivate ApplicationEventMulticaster applicationEventMulticaster;// 应用程序启动度量private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;// 静态指定的侦听器private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();// 刷新前注册的本地侦听器@Nullableprivate Set<ApplicationListener<?>> earlyApplicationListeners;// 在multicaster安装之前发布的ApplicationEvents@Nullableprivate Set<ApplicationEvent> earlyApplicationEvents;// 创建没有父级的新AbstractApplicationContextpublic AbstractApplicationContext() {this.resourcePatternResolver = getResourcePatternResolver();}// 使用给定的父上下文创建新的AbstractApplicationContextpublic 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 DefaultResourceLoaderimplements ConfigurableApplicationContext {public AbstractApplicationContext() {this.resourcePatternResolver = getResourcePatternResolver();}}

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

public class GenericWebApplicationContext extends GenericApplicationContextimplements ConfigurableWebApplicationContext, ThemeSource {@Overrideprotected ResourcePatternResolver getResourcePatternResolver() {// 此处this就是AnnotationConfigServletWebServerApplicationContextreturn 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 就是AnnotationConfigServletWebServerApplicationContextthis.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;@Nullableprivate 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为规范名称的Mapprivate 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为ObjectFactoryprivate 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));// 抑制异常的集合,可用于关联相关原因@Nullableprivate 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继承支持。@Nullableprivate BeanFactory parentBeanFactory;// 如有必要,使用ClassLoader解析bean类名。@Nullableprivate ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();// 如有必要,使用临时ClassLoader解析bean类名@Nullableprivate ClassLoader tempClassLoader;// 标识是缓存bean元数据,还是为每次访问重新获取它private boolean cacheBeanMetadata = true;// bean定义值中表达式的解析策略@Nullableprivate BeanExpressionResolver beanExpressionResolver;// 使用Spring转换服务代替PropertyEditor。@Nullableprivate ConversionService conversionService;// 要应用于此工厂bean的自定义PropertyEditorRegistrarsprivate final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet<>(4);// 要应用于此工厂bean的自定义属性编辑器private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>(4);// 要使用的自定义类型转换器,覆盖默认的PropertyEditor机制@Nullableprivate TypeConverter typeConverter;// 应用于注释属性值等的字符串解析程序private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();// 要应用的BeanPostProcessorsprivate final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();// 预过滤后处理器的缓存@Nullableprivate volatile BeanPostProcessorCache beanPostProcessorCache;// 作用域映射:key为作用域标识符字符串,value为相应的作用域private final Map<String, Scope> scopes = new LinkedHashMap<>(8);// 使用SecurityManager运行时使用的安全上下文@Nullableprivate SecurityContextProvider securityContextProvider;// 合并bean定义:key为bean名称,value为合并的RootBeanDefinitionprivate 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 AbstractBeanFactoryimplements AutowireCapableBeanFactory {// 创建bean实例的策略private InstantiationStrategy instantiationStrategy;// 方法参数名的解析器策略@Nullableprivate 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为BeanWrapperprivate 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<>();// 创建新的AbstractAutowireCapableBeanFactorypublic AbstractAutowireCapableBeanFactory() {super();ignoreDependencyInterface(BeanNameAware.class);ignoreDependencyInterface(BeanFactoryAware.class);ignoreDependencyInterface(BeanClassLoaderAware.class);if (NativeDetector.inNativeImage()) {this.instantiationStrategy = new SimpleInstantiationStrategy();}else {this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();}}// 使用给定父级创建新的AbstractAutowireCapableBeanFactorypublic 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 AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {// javax注入提供程序类@Nullableprivate 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,用于序列化@Nullableprivate String serializationId;// 是否允许重新注册具有相同名称的不同定义private boolean allowBeanDefinitionOverriding = true;// 是否允许即使对于懒加载的 bean也立即加载类private boolean allowEagerClassLoading = true;// 用于依赖项列表和数组的可选OrderComparator@Nullableprivate Comparator<Object> dependencyComparator;// 用于检查bean定义是否为autowire候选项的解析器private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;// 可解析的依赖映射:key为依赖项类型,value为相应的自动注入的值private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);// 从bean定义对象的映射到BeanDefinitionprivate final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);// 从bean名称映射到合并BeanDefinitionHolderprivate 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定义名称的缓存数组@Nullableprivate volatile String[] frozenBeanDefinitionNames;// 是否可以为所有bean缓存bean定义的元数据private volatile boolean configurationFrozen;// 无参构造,具体实现看章节2.3.5public DefaultListableBeanFactory() {super();}// 使用给定的parentBeanFactory创建新的DefaultListableBeanFactorypublic 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 GenericApplicationContextimplements ConfigurableWebApplicationContext, ThemeSource {@Nullableprivate ServletContext servletContext;@Nullableprivate ThemeSource themeSource;// 调用父类GenericApplicationContext的构造方法,具体见章节2.3public GenericWebApplicationContext() {super();}
}
  • 定义了Servlet上下文
  • 定义了主体资源ThemeSource
      触发GenericWebApplicationContext 的初始化时,会调用父类GenericApplicationContext的构造方法,具体见章节2.3

2.5、初始化ServletWebServerApplicationContext

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

public class ServletWebServerApplicationContext extends GenericWebApplicationContextimplements 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 ServletWebServerApplicationContextimplements AnnotationConfigRegistry {private final AnnotatedBeanDefinitionReader reader;private final ClassPathBeanDefinitionScanner scanner;private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();private String[] basePackages;// 创建新的AnnotationConfigServletWebServerApplicationContextpublic 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将被继承,// 否则将创建一个新的创建并使用StandardEnvironmentpublic AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}// 为给定注册表和环境配置创建一个新的AnnotatedBeanDefinitionReader// 以BeanDefinitionRegistry的形式将bean定义加载到的BeanFactorypublic 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();@Nullableprivate String[] autowireCandidatePatterns;private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();private boolean includeAnnotationConfig = true;// 通过给定的BeanFactory创建一个新的ClassPathBeanDefinitionScannerpublic ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {this(registry, true);}// 为给定的beanFactory创建一个新的ClassPathBeanDefinitionScanner,// 如果传入的beanFactory,不仅实现了BeanDefinitionRegistry接口,也实现了ResourceLoader接口,// 它将当做默认的ResourceLoader,通常是ApplicationContext的实现,// 如果给定的是一个普通的BeanDefinitionRegistry,则默认的是它将当做默认的ResourceLoader是PathMatchingResourcePatternResolver,// 如果beanFactory实现了EnvironmentCapable,将会使用到它的环境,否则它就会初始化并使用StandardEnvironment// useDefaultFilters表示是否使用默认的注解比如:@Component、@Repository、@Service、@Controllerpublic 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.ManagedBeanregisterDefaultFilters();}setEnvironment(environment);setResourceLoader(resourceLoader);}
}

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

  useDefaultFilters是指是否要包括的默认过滤器,比如@Component@Repository@Service@Controller
registerDefaultFilters()方法将得到两个AnnotationTypeFilter过滤器,annotationType分别为:org.springframework.stereotype.Component、javax.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();@Overridepublic void setApplicationStartup(ApplicationStartup applicationStartup) {super.setApplicationStartup(applicationStartup);this.beanFactory.setApplicationStartup(applicationStartup);}
}

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

结语

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

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

  1. Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(中)

    目录 一.背景 1.1.刷新的整体调用流程 1.2.本文解读范围 二.调用后处理器 2.1.调用在上下文中注册为beanFactory的后置处理器 2.2.invokeBeanFactoryPostP ...

  2. Alian解读SpringBoot 2.6.0 源码(七):启动流程分析之准备应用上下文

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.准备应用上下文 2.1.整体流程 2.2.设置环境 2.3.应用上下文进行后置处理 2.4.应用所有初始化器 2.5.发布应用上下 ...

  3. Alian解读SpringBoot 2.6.0 源码(十):启动流程之自动装配原理

    目录 一.背景 1.1.主类的加载 1.2.后置处理器的获取 二.配置类后处理器 2.1.获取配置类 2.2. 2.3.解析主类 2.3.1.整体解析过程 2.3.2.核心解析过程 2.3.3.延迟导 ...

  4. Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(下)

    目录 一.背景 1.1.刷新的整体调用流程 1.2.本文解读范围 二.初始化特定上下文子类中的其他特殊bean 2.1.初始化主体资源 2.2.创建web服务 三.检查监听器bean并注册它们 四.实 ...

  5. Alian解读SpringBoot 2.6.0 源码(九):启动流程分析之应用上下文刷新后处理(启动完成事件,Runner运行器,就绪事件)

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.应用上下文刷新后置处理 三.时间信息.输出日志记录执行主类名 四.发布应用上下文启动完成事件 4.1.ApplicationSta ...

  6. Alian解读SpringBoot 2.6.0 源码(二):启动流程分析之监听器解析

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.记录应用启动的开始时间 三.初始化启动上下文 3.1.初始化启动上下文 3.2.初始化应用程序事件广播器 3.3.初始化应用上下文 ...

  7. Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(上)

    目录 一.背景 1.1.run方法整体流程 1.2.刷新的整体调用流程 1.3.本文解读范围 二.准备刷新 2.1.准备刷新的流程 2.2.初始化上下文环境中servlet相关属性源 2.3.校验re ...

  8. Alian解读SpringBoot 2.6.0 源码(四):启动流程分析之应用环境准备

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.应用环境准备 2.1.准备环境的整体流程 2.2.创建环境 2.3.配置环境 2.3.1.注册默认的转换器.格式化组件 2.3.1 ...

  9. Alian解读SpringBoot 2.6.0 源码(一):SpringApplication对象创建(Spring工厂加载机制)

    目录 一.背景 二.SpringApplication实例化 2.1.实例化方法入口 2.2.推断应用程序类型 2.3.Spring工厂加载机制 2.3.1.获取Spring工厂实例(重要) 2.3. ...

最新文章

  1. Linux实战教学笔记32:企业级Memcached服务应用实践
  2. python支持double吗_python列表理解为double
  3. boost::geometry::assign用法的测试程序
  4. 会话创建过程-创建Executor
  5. startlogging中设置setstdout=false来禁用这个功能。_Windows 10禁用USB选择性暂停设置,峰哥教你解决USB设备失灵问题...
  6. “懒癌”患者福音:是时候找一个AI帮你做家务了
  7. 《21天学通HTML+CSS+JavaScript Web开发(第7版)》——1.4 统一资源定位符
  8. python测试系列教程——python+Selenium+chrome自动化测试框架
  9. 用户行为分析面面观之一
  10. Python给指定QQ好友自动发送信息和图片
  11. Vue--改变鼠标指针的图片
  12. 移动营业厅前台设备如何安装+新手引导
  13. docker部署tf-serving模型
  14. Deepin15.11修改分区系统无法启动问题
  15. 记录:Flink checkpoint 过期导致失败(线上问题)
  16. canvas实现图片旋转
  17. linux内核开启otg,OTG驱动分析(一)
  18. 三维扫描仪可以做什么?
  19. 远控免杀专题(12)-Green-Hat-Suite免杀(VT免杀率23/70)
  20. 移动桌面位置,再也不怕C盘爆满!

热门文章

  1. 8.8.3. Line Segments
  2. chmod参数u+s
  3. 【量化笔记】波动volatility相关技术指标以其含义
  4. [CMU 15-445] 08 树索引 -Ⅱ
  5. C语言因式分解的程序框图,C语言 · 因式分解
  6. 一看就懂关于阿里云服务器地域和可用区的选择方法
  7. 动态规划之背包问题(01背包问题、完全背包问题、多重背包问题 I、多重背包问题 II 、分组背包问题)
  8. android 仿Boss直聘消息界面
  9. Java中joda日期格式化工具的使用
  10. 软件设计模式--第一章 软件设计模式基础