SpringApplication的run方法

public ConfigurableApplicationContext run(String... args) {//时间监控StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();//java.awt.headless是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true,系统变量默认为trueconfigureHeadlessProperty();//获取spring.factories中的监听器变量,args为指定的参数数组,默认为当前类SpringApplication//第一步:获取并启动监听器SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//第二步:构造容器环境ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);//设置需要忽略的beanconfigureIgnoreBeanInfo(environment);//第三步:打印banner和创建容器Banner printedBanner = printBanner(environment);context = createApplicationContext();//第四步:实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);//第五步:准备容器prepareContext(context, environment, listeners, applicationArguments,printedBanner);//第六步:刷新容器refreshContext(context);//第七步:刷新容器后的扩展接口afterRefresh(context, applicationArguments);stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}//第八步:监听器已启动listeners.started(context);//第九步:执行ApplicationRunner和CommandLineRunnercallRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}try {listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;}

第一步:获取并启动监听器

1.获取运行监听器
SpringApplication

     SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();
 private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

EventPublishingRunListener实例化,添加10个监听器

 public EventPublishingRunListener(SpringApplication application, String[] args) {this.application = application;this.args = args;this.initialMulticaster = new SimpleApplicationEventMulticaster();for (ApplicationListener<?> listener : application.getListeners()) {this.initialMulticaster.addApplicationListener(listener);}}

AbstractApplicationEventMulticaster先去掉监听器的代理对象,然后添加监听器对象

 @Overridepublic void addApplicationListener(ApplicationListener<?> listener) {synchronized (this.retrievalMutex) {// Explicitly remove target for a proxy, if registered already,// in order to avoid double invocations of the same listener.Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);if (singletonTarget instanceof ApplicationListener) {this.defaultRetriever.applicationListeners.remove(singletonTarget);}this.defaultRetriever.applicationListeners.add(listener);this.retrieverCache.clear();}}

SpringApplicationRunListeners 存储运行监听器

 private final List<SpringApplicationRunListener> listeners;SpringApplicationRunListeners(Log log,Collection<? extends SpringApplicationRunListener> listeners) {this.log = log;this.listeners = new ArrayList<>(listeners);}

2.运行监听器启动starting
SpringApplicationRunListeners

 public void starting() {for (SpringApplicationRunListener listener : this.listeners) {listener.starting();}}

EventPublishingRunListener

 private final SimpleApplicationEventMulticaster initialMulticaster;@Overridepublic void starting() {this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));}

SimpleApplicationEventMulticaster

 @Overridepublic void multicastEvent(ApplicationEvent event) {multicastEvent(event, resolveDefaultEventType(event));}@Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {Executor executor = getTaskExecutor();if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}}

AbstractApplicationEventMulticaster

 final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {Object source = event.getSource();Class<?> sourceType = (source != null ? source.getClass() : null);ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);// Quick check for existing entry on ConcurrentHashMap...ListenerRetriever retriever = this.retrieverCache.get(cacheKey);if (retriever != null) {return retriever.getApplicationListeners();}if (this.beanClassLoader == null ||(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {// Fully synchronized building and caching of a ListenerRetrieversynchronized (this.retrievalMutex) {retriever = this.retrieverCache.get(cacheKey);if (retriever != null) {return retriever.getApplicationListeners();}retriever = new ListenerRetriever(true);Collection<ApplicationListener<?>> listeners =retrieveApplicationListeners(eventType, sourceType, retriever);this.retrieverCache.put(cacheKey, retriever);return listeners;}}else {// No ListenerRetriever caching -> no synchronization necessaryreturn retrieveApplicationListeners(eventType, sourceType, null);}}

SimpleApplicationEventMulticaster

 protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = getErrorHandler();if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);}}else {doInvokeListener(listener, event);}}private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception and just log a debug message.Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) {logger.debug("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

LoggingApplicationListener打印日志

 @Overridepublic void onApplicationEvent(ApplicationEvent event) {//在springboot启动的时候if (event instanceof ApplicationStartedEvent) {onApplicationStartedEvent((ApplicationStartedEvent) event);}//springboot的Environment环境准备完成的时候else if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}//在springboot容器的环境设置完成以后else if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent((ApplicationPreparedEvent) event);}//容器关闭的时候else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event).getApplicationContext().getParent() == null) {onContextClosedEvent();}//容器启动失败的时候else if (event instanceof ApplicationFailedEvent) {onApplicationFailedEvent();}}private void onApplicationStartingEvent(ApplicationStartingEvent event) {this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());this.loggingSystem.beforeInitialize();}

因为我们的事件类型为ApplicationStartedEvent,所以会执行onApplicationStartedEvent((ApplicationStartedEvent) event);。springBoot会在运行过程中的不同阶段,发送各种事件,来执行对应监听器的对应方法。

二:环境构建

SpringApplication

 private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environment//获取对应的ConfigurableEnvironmentConfigurableEnvironment environment = getOrCreateEnvironment();//配置configureEnvironment(environment, applicationArguments.getSourceArgs());//发布环境已准备事件,这是第二次发布事件listeners.environmentPrepared(environment);bindToSpringApplication(environment);if (this.webApplicationType == WebApplicationType.NONE) {environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);}ConfigurationPropertySources.attach(environment);return environment;}//返回StandardServletEnvironmentprivate ConfigurableEnvironment getOrCreateEnvironment() {if (this.environment != null) {return this.environment;}switch (this.webApplicationType) {case SERVLET:return new StandardServletEnvironment();case REACTIVE:return new StandardReactiveWebEnvironment();default:return new StandardEnvironment();}}

SpringApplicationRunListeners

public void environmentPrepared(ConfigurableEnvironment environment) {for (SpringApplicationRunListener listener : this.listeners) {listener.environmentPrepared(environment);}}

EventPublishingRunListener从10个监听器中,选出ApplicationEnvironmentPreparedEvent类型的,调用监听器

 private final SimpleApplicationEventMulticaster initialMulticaster;@Overridepublic void environmentPrepared(ConfigurableEnvironment environment) {this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));}

SimpleApplicationEventMulticaster

 @Overridepublic void multicastEvent(ApplicationEvent event) {multicastEvent(event, resolveDefaultEventType(event));}@Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {Executor executor = getTaskExecutor();if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}}protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = getErrorHandler();if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);}}else {doInvokeListener(listener, event);}}private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception and just log a debug message.Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) {logger.debug("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

比如有ConfigFileApplicationListener,加载配置文件EnvironmentPostProcessor的3个后处理器

@Overridepublic void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent(event);}}private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();postProcessors.add(this);AnnotationAwareOrderComparator.sort(postProcessors);for (EnvironmentPostProcessor postProcessor : postProcessors) {postProcessor.postProcessEnvironment(event.getEnvironment(),event.getSpringApplication());}}List<EnvironmentPostProcessor> loadPostProcessors() {return SpringFactoriesLoader.loadFactories(EnvironmentPostProcessor.class,getClass().getClassLoader());}
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor

第三步:打印banner和创建容器

SpringApplication

         Banner printedBanner = printBanner(environment);context = createApplicationContext();
 public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."+ "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";//返回AnnotationConfigServletWebServerApplicationContextprotected ConfigurableApplicationContext createApplicationContext() {Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {try {switch (this.webApplicationType) {case SERVLET:contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);break;case REACTIVE:contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);break;default:contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);}}catch (ClassNotFoundException ex) {throw new IllegalStateException("Unable create a default ApplicationContext, "+ "please specify an ApplicationContextClass",ex);}}return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);}

AnnotationConfigServletWebServerApplicationContext

 public AnnotationConfigServletWebServerApplicationContext() {this.reader = new AnnotatedBeanDefinitionReader(this);this.scanner = new ClassPathBeanDefinitionScanner(this);}

AnnotatedBeanDefinitionReader

 public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}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);}

AnnotationConfigUtils

 public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);}public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME ="org.springframework.context.annotation.internalConfigurationAnnotationProcessor";public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}//注册了6个内部bean,默认容量是8,加载因子是0.75,正好是6个Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}

注册了内部bean,名称比较奇怪,不是类的简单名称的首字母小写,而是全限定名前面加上internal

ConfigurationClassPostProcessor比较重要,后面的自动配置用到了

第四步:报告错误信息

exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);
# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
在这里插入代码片

该类主要是在项目启动失败之后,打印log:

 private void reportFailure(Collection<SpringBootExceptionReporter> exceptionReporters,Throwable failure) {try {for (SpringBootExceptionReporter reporter : exceptionReporters) {if (reporter.reportException(failure)) {//上报错误logregisterLoggedException(failure);return;}}}catch (Throwable ex) {// Continue with normal handling of the original failure}if (logger.isErrorEnabled()) {logger.error("Application run failed", failure);registerLoggedException(failure);}}

第五步:准备容器

这一步主要是在容器刷新之前的准备动作。包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。
SpringApplication

private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {//设置容器环境,包括各种变量context.setEnvironment(environment);//执行容器后置处理postProcessApplicationContext(context);//执行容器中的ApplicationContextInitializer(包括 spring.factories和自定义的实例)applyInitializers(context);//发送容器已经准备好的事件,通知各监听器listeners.contextPrepared(context);//打印logif (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beans//注册启动参数bean,这里将容器指定的参数封装成bean,注入容器context.getBeanFactory().registerSingleton("springApplicationArguments",applicationArguments);//设置bannerif (printedBanner != null) {context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);}// Load the sources//获取我们的启动类指定的参数,可以是多个Set<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");//加载我们的启动类,将启动类注入容器load(context, sources.toArray(new Object[0]));//发布容器已加载事件。listeners.contextLoaded(context);}

容器的后置处理,这里默认不执行任何逻辑,因为beanNameGenerator和resourceLoader默认为空。之所以这样做,是springBoot留给我们的扩展处理方式

 protected void postProcessApplicationContext(ConfigurableApplicationContext context) {if (this.beanNameGenerator != null) {context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,this.beanNameGenerator);}if (this.resourceLoader != null) {if (context instanceof GenericApplicationContext) {((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);}if (context instanceof DefaultResourceLoader) {((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());}}}

applyInitializers加载4个初始化器的共3个内部后处理器

 protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");initializer.initialize(context);}}
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

比如ConfigurationWarningsApplicationContextInitializer

 protected static final class ConfigurationWarningsPostProcessorimplements PriorityOrdered, BeanDefinitionRegistryPostProcessor {...}@Overridepublic void initialize(ConfigurableApplicationContext context) {context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));}

加载启动指定类(重点)
这里会将我们的启动类加载spring容器beanDefinitionMap中,为后续springBoot 自动化配置奠定基础,springBoot为我们提供的各种注解配置也与此有关。

 protected void load(ApplicationContext context, Object[] sources) {if (logger.isDebugEnabled()) {logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));}BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);if (this.beanNameGenerator != null) {loader.setBeanNameGenerator(this.beanNameGenerator);}if (this.resourceLoader != null) {loader.setResourceLoader(this.resourceLoader);}if (this.environment != null) {loader.setEnvironment(this.environment);}loader.load();}

需要注意的是,springBoot2会优先选择groovy加载方式,找不到再选用java方式。或许groovy动态加载class文件的性能更胜一筹。
但是还是默认选择java加载
BeanDefinitionLoader

 public int load() {int count = 0;for (Object source : this.sources) {count += load(source);}return count;}选择类加载private int load(Object source) {Assert.notNull(source, "Source must not be null");if (source instanceof Class<?>) {return load((Class<?>) source);}if (source instanceof Resource) {return load((Resource) source);}if (source instanceof Package) {return load((Package) source);}if (source instanceof CharSequence) {return load((CharSequence) source);}throw new IllegalArgumentException("Invalid source type " + source.getClass());}private final AnnotatedBeanDefinitionReader annotatedReader;private int load(Class<?> source) {if (isGroovyPresent()&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {// Any GroovyLoaders added in beans{} DSL can contribute beans hereGroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,GroovyBeanDefinitionSource.class);load(loader);}if (isComponent(source)) {//以注解的方式,将启动类bean信息存入beanDefinitionMapthis.annotatedReader.register(source);return 1;}return 0;}启动类SpringBootApplication注解,里面继承Configuration注解,继承Component注解,返回trueprivate boolean isComponent(Class<?> type) {// This has to be a bit of a guess. The only way to be sure that this type is// eligible is to make a bean definition out of it and try to instantiate it.if (AnnotationUtils.findAnnotation(type, Component.class) != null) {return true;}// Nested anonymous classes are not eligible for registration, nor are groovy// closuresif (type.getName().matches(".*\\$_.*closure.*") || type.isAnonymousClass()|| type.getConstructors() == null || type.getConstructors().length == 0) {return false;}return true;}

AnnotatedBeanDefinitionReader

 public void register(Class<?>... annotatedClasses) {for (Class<?> annotatedClass : annotatedClasses) {registerBean(annotatedClass);}}public void registerBean(Class<?> annotatedClass) {doRegisterBean(annotatedClass, null, null, null);}<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}abd.setInstanceSupplier(instanceSupplier);ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);abd.setScope(scopeMetadata.getScopeName());String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);if (qualifiers != null) {for (Class<? extends Annotation> qualifier : qualifiers) {if (Primary.class == qualifier) {abd.setPrimary(true);}else if (Lazy.class == qualifier) {abd.setLazyInit(true);}else {abd.addQualifier(new AutowireCandidateQualifier(qualifier));}}}for (BeanDefinitionCustomizer customizer : definitionCustomizers) {customizer.customize(abd);}BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);}

我们的启动类就被包装成AnnotatedGenericBeanDefinition了,后续启动类的处理都基于该对象了。

通知监听器,容器已准备就绪

listeners.contextLoaded(context);

主还是针对一些日志等监听器的响应处理。

第六步:刷新容器

refresh方法在spring整个源码体系中举足轻重,是实现 ioc 和 aop的关键
SpringApplication

 protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);((AbstractApplicationContext) applicationContext).refresh();}

AbstractApplicationContext

synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing./*** 刷新上下文环境* 初始化上下文环境,对系统的环境变量或者系统属性进行准备和校验* 如环境变量中必须设置某个值才能运行,否则不能运行,这个时候可以在这里加这个校验,* 重写initPropertySources方法就好了*/prepareRefresh();// Tell the subclass to refresh the internal bean factory./*** 初始化BeanFactory,解析XML,相当于之前的XmlBeanFactory的操作,*/ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context./*** 为上下文准备BeanFactory,即对BeanFactory的各种功能进行填充,如常用的注解@Autowired @Qualifier等* 设置SPEL表达式#{key}的解析器* 设置资源编辑注册器,如PerpertyEditorSupper的支持* 添加ApplicationContextAwareProcessor处理器* 在依赖注入忽略实现*Aware的接口,如EnvironmentAware、ApplicationEventPublisherAware等* 注册依赖,如一个bean的属性中含有ApplicationEventPublisher(beanFactory),则会将beanFactory的实例注入进去*/prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses./*** 提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess*/postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context./*** 激活各种BeanFactory处理器,包括BeanDefinitionRegistryBeanFactoryPostProcessor和普通的BeanFactoryPostProcessor* 执行对应的postProcessBeanDefinitionRegistry方法 和  postProcessBeanFactory方法*/invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation./*** 注册拦截Bean创建的Bean处理器,即注册BeanPostProcessor,不是BeanFactoryPostProcessor,注意两者的区别* 注意,这里仅仅是注册,并不会执行对应的方法,将在bean的实例化时执行对应的方法*/registerBeanPostProcessors(beanFactory);// Initialize message source for this context./*** 初始化上下文中的资源文件,如国际化文件的处理等*/initMessageSource();// Initialize event multicaster for this context./*** 初始化上下文事件广播器,并放入applicatioEventMulticaster,如ApplicationEventPublisher*/initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses./*** 给子类扩展初始化其他Bean*/onRefresh();// Check for listener beans and register them./*** 在所有bean中查找listener bean,然后注册到广播器中*/registerListeners();// Instantiate all remaining (non-lazy-init) singletons./*** 设置转换器* 注册一个默认的属性值解析器* 冻结所有的bean定义,说明注册的bean定义将不能被修改或进一步的处理* 初始化剩余的非惰性的bean,即初始化非延迟加载的bean*/finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event./*** 初始化生命周期处理器DefaultLifecycleProcessor,DefaultLifecycleProcessor含有start方法和stop方法,spring启动的时候调用start方法开始生命周期,* spring关闭的时候调用stop方法来结束生命周期,通常用来配置后台程序,启动有一直运行,如一直轮询kafka* 启动所有实现了Lifecycle接口的类* 通过spring的事件发布机制发布ContextRefreshedEvent事件,以保证对应的监听器做进一步的处理,即对那种在spring启动后需要处理的一些类,这些类实现了* ApplicationListener<ContextRefreshedEvent> ,这里就是要触发这些类的执行(执行onApplicationEvent方法)另外,spring的内置Event有ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、RequestHandleEvent* 完成初始化,通知生命周期处理器lifeCycleProcessor刷新过程,同时发出ContextRefreshEvent通知其他人*/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();}}

第七步:刷新容器后的扩展接口

protected void afterRefresh(ConfigurableApplicationContext context,ApplicationArguments args) {}

扩展接口,设计模式中的模板方法,默认为空实现。如果有自定义需求,可以重写该方法。比如打印一些启动结束log,或者一些其它后置处理。

springboot2源码2-SpringApplication运行相关推荐

  1. jsp人事管理系统_Jsp+Ssm+Mysql实现的医院人事管理系统源码附带视频运行教程

    项目地址: jsp+ssm+mysql实现的医院人事管理系统源码附带视频运行教程|猿来入此[beta]多用户版IT项目教程源码分享网站​www.yuanlrc.com 今天给大家演示的是一款由jsp+ ...

  2. 基于SpringBoot+Vue的酒店管理系统(免费获取源码+项目介绍+运行介绍+运行截图+论文)

    技术架构 后端:SpringBoot+SpringMVC+Mybatis-Plus 前端:vue+ElementUI+HTML+js+css+jquery+Nginx 数据库:MySQL+Thymel ...

  3. Android实现车辆检测(含Android源码 可实时运行)

    Android实现车辆检测(含Android源码 可实时运行) 目录 Android实现车辆检测(含Android源码 可实时运行) 1. 前言 2. 车辆检测数据集说明 3. 基于YOLOv5的车辆 ...

  4. 神经网络 c++ 源码 可以直接复制运行,提供数据集,操作简单,最少仅需4行代码

    神经网络 c++ 源码 可以直接复制运行,提供数据集,操作简单,最少仅需4行代码 本文的神经网络,让你省去Python那些花里胡哨的变量名,最少仅需4行代码即可完成自己的神经网络** 本文章采用c++ ...

  5. .Net6.0快速开发平台3.4新版源码(教程运行视频齐全),net敏捷开发

    .Net6.0快速开发平台3.4新版源码(教程运行视频齐全),net敏捷开发,全网最新有演示,报表设计,大屏设计,流程设计,实时通讯,动态表单,日程管理,APP端,双端代码生成全部具备,是你接外包的利 ...

  6. obs-studio源码 test程序运行错误解决

    obs-studio源码 test程序运行错误解决 最新的代码,在win10下用cmake生成vs2019的工程,编译成功. 但是跑win-test.exe时却错误,原因参考一位博主的文章<ob ...

  7. java选课系统代码mysql_Java swing mysql实现的学生选课系统项目源码附带视频运行教程...

    大家好,今天给大家演示一下由Java swing实现的一款简单的学生选课系统,数据库采用的是mysql,实现了简单的选课功能,后面的课程中我们会出Java web版的学生选课系统,今天先看Java s ...

  8. Android实现红绿灯检测(含Android源码 可实时运行)

    Android实现红绿灯检测(含Android源码 可实时运行) 目录 Android实现红绿灯检测(含Android源码 可实时运行) 1. 前言 2. 红绿灯检测数据集说明 3. 基于YOLOv5 ...

  9. 5.3.3.tat.gz php_一步步在LINUX中源码安装PHP运行平台

    一步步在LINUX中源码安装PHP运行平台 一步步在LINUX中源码安装PHP运行平台 本人是LINUX新手, 今天我们要学习一下如何在LINUX环境下安装PHP运行环境 目标:在LINUX环境下源码 ...

最新文章

  1. 1 张图,拆解阿里 P8高级架构师必会技术栈!
  2. decode函数_decode函数的妙用网友的两个问题解答
  3. SpringBoot2.0新特性 - Quartz自动化配置集成
  4. 基于存储过程的ASP.NET用户登录示例
  5. 2015服务器性能排名,【新年大礼】史上最全CPU天梯图2015年V3.5版 全平台性能对比参考...
  6. SpringBoot学习笔记(8):事物处理
  7. 使用DOM4J解析XML及采用Schema校验的方法
  8. [渗透测试] DOS攻击
  9. 对非线程安全类ListT的一些总结
  10. 用Java写一个浪费cpu的程序_Java程序是如何浪费内存的
  11. 一、ssh 协议:SSH 传输层协议
  12. Matlab中struct的用法
  13. STM8S103 LCD5110例程带字库
  14. 十分钟学懂Python入门基础3(中)
  15. 怎么压缩图片的大小?这几个方法你不能不知道
  16. Mysql从入门到入魔——5. 聚集、分组、子查询
  17. 机器视觉测量原理及其优势
  18. transferTo和transferFrom
  19. Batchnorm 和Layernorm 区别
  20. 两名老人接力营救轻生女子一人溺亡

热门文章

  1. Linux---文件、软链接于硬链接文件
  2. 【零基础学Java】—static关键字概述(十六)
  3. DevTools failed to load source map: Could not load content for…System error: net::ERR_FILE_NOT_FOUN
  4. 句句真研—每日长难句打卡Day19
  5. 前端—每天5道面试题(3)
  6. HTML+CSS制作3D步数统计界面
  7. mysql openrowset_SQL的OPENROWSET开启和使用方法
  8. 一套代码在不同的电脑执行快慢_电脑如何选配之硬盘篇
  9. windows 设置 rocketmq环境变量_RocketMQ 开篇
  10. SQL68 牛客每个人最近的登录日期(三)