Spring-Boot启动类解析,启动全流程梳理

Spring Boot 源码解析
一. 启动类内容

public static void main(String[] args) {
	// 实例化SpringApplication
        SpringApplication sa = new SpringApplication(JARApplication.class);
//        sa.addInitializers(); // 自定义加载器
//        sa.addListeners();    // 自定义监听器
        sa.run(args);
}

二. SpringApplication实例化解析

	// 是否是web环境
	private boolean webEnvironment;
	// 用来判断是否是web环境的
	private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
		"org.springframework.web.context.ConfigurableWebApplicationContext" };

	private final Set<Object> sources = new LinkedHashSet<Object>();
	private List<ApplicationContextInitializer<?>> initializers;
	private List<ApplicationListener<?>> listeners;
	private Class<?> mainApplicationClass;

	public SpringApplication(Object... sources) {
		initialize(sources);
	}
	// 实例化方法
	private void initialize(Object[] sources) {
		// 将传入的"JARApplication"放入Set<Object> sources集合中。
		if (sources != null && sources.length > 0) {
			this.sources.addAll(Arrays.asList(sources));
		}
		// 判断是否是web环境
		this.webEnvironment = deduceWebEnvironment();
		// 创建并初始化ApplicationContextInitializer列表
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		// 创建并初始化ApplicationListener列表
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

		this.mainApplicationClass = deduceMainApplicationClass();
	}

initialize方法做了下列内容

1. 将传入的"JARApplication"放入Set<Object> sources集合中。
2. 判断是否是web环境

private boolean deduceWebEnvironment() {
		// 循环String[] WEB_ENVIRONMENT_CLASSES看是否存在。
		for (String className : WEB_ENVIRONMENT_CLASSES) {
			// 判断由提供的类名(类的全限定名)标识的类是否存在并可以加载
			if (!ClassUtils.isPresent(className, null)) {
				return false;
			}
		}
		return true;
	}

3. 创建并初始化ApplicationContextInitializer列表

public void setInitializers(
			Collection<? extends ApplicationContextInitializer<?>> initializers) {
		// 初始化一个ArrayList。
		this.initializers = new ArrayList<ApplicationContextInitializer<?>>();
		// 将所有的initializers传入
		this.initializers.addAll(initializers);
	}
	// 获取initializer列表,type是ApplicationContextInitializer.class
	private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
		return getSpringFactoriesInstances(type, new Class<?>[] {});
	}

	private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
			Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		// 使用名称并确保唯一以防止重复, 获取要加载的initializer
		Set<String> names = new LinkedHashSet<String>(
				SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		// 根据名称实例化,就是用反射创建对象,
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
				classLoader, args, names);
		// 排序
		AnnotationAwareOrderComparator.sort(instances);
		// 返回集合
		return instances;
	}

	// 获取name
	public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
		String factoryClassName = factoryClass.getName();
		try {
			// 获取配置文件路径。其实就是从Maven仓库中的spring-boot-1.4.3.RELEASE.jar以及spring-boot-autoconfigure-1.4.3.RELEASE.jar的META-INF/spring.factories中获取key为org.springframework.context.ApplicationContextInitializer的所有initializers全类名
			// spring-boot.jar下的配置信息
			// org.springframework.context.ApplicationContextInitializer=\
			// org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
			// org.springframework.boot.context.ContextIdApplicationContextInitializer,\
			// org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
			// org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer
			// spring-boot-autoconfigure.jar下的配置信息
			// org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
			// org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
			// 默认是加载这6个初始化器
			Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			List<String> result = new ArrayList<String>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
				String factoryClassNames = properties.getProperty(factoryClassName);
				result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
			}
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
					"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}

4. 创建并初始化ApplicationListener列表

// 与ApplicationContextInitializer初始化的步骤一致,获取的同样是默认配置文件下的ApplicationListener内容

5. 初始化主类mainApplicationClass

// 初始化主类方法
	private Class<?> deduceMainApplicationClass() {
		try {
			// 调用的函数堆栈,这里解释下其实就是从main方法进来到SpringApplication方法,再到initialize方法再到deduceMainApplicationClass
			// 那这个stackTrace就有4个元素。找到方法名是main的方法就是找到最开始的main方法,然后根据方法反射找到主类
			StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
			for (StackTraceElement stackTraceElement : stackTrace) {
				if ("main".equals(stackTraceElement.getMethodName())) {
					return Class.forName(stackTraceElement.getClassName());
				}
			}
		}
		catch (ClassNotFoundException ex) {
			// Swallow and continue
		}
		return null;
	}

三. 添加自定义监听器、自定义初始化器

	// 相当于在initializers或者listeners的数组中添加元素
	public void setInitializers(
			Collection<? extends ApplicationContextInitializer<?>> initializers) {
		this.initializers = new ArrayList<ApplicationContextInitializer<?>>();
		this.initializers.addAll(initializers);
	}

四、启动核心run方法

/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 */
	public ConfigurableApplicationContext run(String... args) {
		// 创建计时器
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;
		// 设置awt系统属性。
		configureHeadlessProperty();
		// 获取SpringApplicationRunListeners
		SpringApplicationRunListeners listeners = getRunListeners(args);、
		// 启动listeners
		listeners.starting();
		try {
			// 创建ApplicationArguments
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			// 创建并初始化ConfigurableEnvironment
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			// 打印banner
			Banner printedBanner = printBanner(environment);
			// 创建ConfigurableApplicationContext
			context = createApplicationContext();
			// 创建FailureAnalyzers对象
			analyzers = new FailureAnalyzers(context);
			// 准备ConfigurableApplicationContext
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			// 刷新ConfigurableApplicationContext
			refreshContext(context);
			// 刷新后动作
			afterRefresh(context, applicationArguments);
			// 发布finish事件
			listeners.finished(context, null);
			// 定时器stop
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			return context;
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, analyzers, ex);
			throw new IllegalStateException(ex);
		}
	}

    1. 创建计时器
    2. 设置awt系统属性
    3. 获取SpringApplicationRunListeners

// 与之前初始化initializer和listener一样,从spring-boot的jar包的配置文件spring.factories中读取SpringApplicationRunListeners全类名的配置信息,之后创建该对象
	// 配置信息内容。EventPublishingRunListener用来发布事件,触发监听器
	// org.springframework.boot.context.event.EventPublishingRunListener
	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
				SpringApplicationRunListener.class, types, this, args));
	}
	// 实例化EventPublishingRunListener放入SpringApplicationRunListeners中
	SpringApplicationRunListeners(Log log,
			Collection<? extends SpringApplicationRunListener> listeners) {
		this.log = log;
		this.listeners = new ArrayList<SpringApplicationRunListener>(listeners);
	}

	// 这里是EventPublishingRunListener的源码
	private final SpringApplication application;

	private final String[] args;
	
	private final SimpleApplicationEventMulticaster initialMulticaster;

	public EventPublishingRunListener(SpringApplication application, String[] args) {
		// 这个是把刚实例化号的SpringApplication传入,里边有所有的listener包括自定义的
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();
		// 将所有的listener都添加到initialMulticaster示例中,这样当initialMulticaster发布事件时,监听器监听到该时间就会做出相应的动作。
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}

4. 启动listeners

// SpriongApplicationRunListener的starting方法,会调用它包含的所有的listener的starting方法,这里listener只有一个就是EventPublishingRunListener
	public void starting() {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.starting();
		}
	}
	// EventPublishingRunListener的启动方法。回忆一下,initialMulticaster中已经加载了SpringApplication中所有的listener
	@Override
	@SuppressWarnings("deprecation")
	public void starting() {
		// 广播,所有监听了该事件的监听器都会执行相应的方法。
		this.initialMulticaster
				.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
	}

5. 创建ApplicationArguments

// 创建的过程,source会多层实例化,source的父类是SimpleCommandLinePropertySource的父类是CommandLinePropertySource的父类是EnumerablePropertySource的父类是PropertySource
	public DefaultApplicationArguments(String[] args) {
		Assert.notNull(args, "Args must not be null");
		this.source = new Source(args);
		this.args = args;
	}
	// 调用多个父类构造参数,执行到最后的结果是args和source。
	// source的结果是 T source = CommandLineArgs;
	class CommandLineArgs {
	// optionArgs就是key,values的结果。举例:args = {--spring.output.ansi.enabled=always}, optionArgs = k:spring.output.ansi.enabled, v:{always}。其中v是一个list。
	private final Map<String, List<String>> optionArgs = new HashMap<String, List<String>>();
	private final List<String> nonOptionArgs = new ArrayList<String>();

 

6. 创建并初始化ConfigurableEnvironment

// 
	private ConfigurableEnvironment prepareEnvironment(
			SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		// 创建一个ConfigurableEnvironment实例
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		// 配置ConfigurableEnvironment实例
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		// 发布ApplicationEnvironmentPreparedEvent事件
		listeners.environmentPrepared(environment);
		if (!this.webEnvironment) {
			environment = new EnvironmentConverter(getClassLoader())
					.convertToStandardEnvironmentIfNecessary(environment);
		}
		return environment;
	}
	// (1)、创建ConfigurableEnvironment的代码
	private ConfigurableEnvironment getOrCreateEnvironment() {
		if (this.environment != null) {
			return this.environment;
		}
		// 这里webEnvironment是true,所以创建的是StandardServletEnvironment
		if (this.webEnvironment) {
			return new StandardServletEnvironment();
		}
		return new StandardEnvironment();
	}
	// 实例化StandardServletEnvironment 会先调用其父类AbstractEnvironment的构造器
	// MutablePropertySources是PropertySources的子类,PropertySources中的一个属性propertySourceList会存放所有的属性源PropertySource
	private final MutablePropertySources propertySources = new MutablePropertySources(this.logger);

	private final ConfigurablePropertyResolver propertyResolver =
			new PropertySourcesPropertyResolver(this.propertySources);
	public AbstractEnvironment() {
		// 调用该方法,为propertySources增加PropertySource
		customizePropertySources(this.propertySources);
		if (logger.isDebugEnabled()) {
			logger.debug("Initialized " + getClass().getSimpleName() + " with PropertySources " + this.propertySources);
		}
	}
	// StandardServletEnvironment中的实例化方法,增加两个属性源,
	@Override
	protected void customizePropertySources(MutablePropertySources propertySources) {
		// 增加name为servletConfigInit-Params的属性源
		propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
		// 增加name为servletContextInitParams的属性源
		propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
		if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
			propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
		}
		// 调用StandardServletEnvironment父类的customizePropertySources方法
		super.customizePropertySources(propertySources);
	}
	// 父类的customizePropertySources方法,也是增加了两个属性源
	@Override
	protected void customizePropertySources(MutablePropertySources propertySources) {
		// 增加了SystemProperties的属性源,值为一个Map,存放了jvm的系统属性例如java.runtime.name - Java(TM) SE Runtime Environment这种键值对,
		// 其中在启动jvm的参数中设置了server.port=8088,这个值就被放到这个map中了,里边存放了55个键值对
		propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
		// 这个属性源为SystemEnvironmentPropertySource,主要存放一些系统环境属性,比如从环境变量文件中读取的M2_HOME等。里边暂时存放了21个键值对
		propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
	}
	// 到这里ConfigurableEnvironment的示例就创建成功了。里边总共包含了下列东西:
	// 1、 不包含任何元素的LinkedHashSet,name为activeProfiles;
	// 2、 一个包含default元素的LinkedHashSet,name是defaultProfiles。
	// 3、 一个MutablePropertySources,其中包含4个属性源。
	// 4、 一个PropertySourcesPropertyResolver属性,主要用于解析属性源,其内部包含3描述的MutablePropertySources的属性。以及用于解析属性源的其他属性。


	// (2).配置ConfigurableEnvironment实例的代码,其实就是配置activeProfiles和PropertySources两个list。
	protected void configureEnvironment(ConfigurableEnvironment environment,
			String[] args) {
		// 配置PropertySources
		configurePropertySources(environment, args);
		// 配置activeProfiles
		configureProfiles(environment, args);
	}
	// 配置PropertySources的源码
	protected void configurePropertySources(ConfigurableEnvironment environment,
			String[] args) {
		// 实例化MutablePropertySources
		MutablePropertySources sources = environment.getPropertySources();
		// 将default属性源加入
		if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
			sources.addLast(
					new MapPropertySource("defaultProperties", this.defaultProperties));
		}
		// args参数解析并加入Sources中
		if (this.addCommandLineProperties && args.length > 0) {
			String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
			if (sources.contains(name)) {
				PropertySource<?> source = sources.get(name);
				CompositePropertySource composite = new CompositePropertySource(name);
				composite.addPropertySource(new SimpleCommandLinePropertySource(
						name + "-" + args.hashCode(), args));
				composite.addPropertySource(source);
				sources.replace(name, composite);
			}
			else {
				// 创建了一个SimpleCommandLinePropertySource,并将该属性源放入source的首部,表明优先级最高
				sources.addFirst(new SimpleCommandLinePropertySource(args));
			}
		}
	}
	// 配置activeProfiles的源码,其实就是读取spring.profiles.active所指定的配置文件
	protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
		// 先get一下,确保它们已初始化
		environment.getActiveProfiles(); // ensure they are initialized
		// But these ones should go first (last wins in a property key clash)
		Set<String> profiles = new LinkedHashSet<String>(this.additionalProfiles);
		profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
		environment.setActiveProfiles(profiles.toArray(new String[profiles.size()]));
	}

	// (3). 发布 ApplicationEnvironmentPreparedEvent事件的代码与starting事件发布类似
	public void environmentPrepared(ConfigurableEnvironment environment) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.environmentPrepared(environment);
		}
	}
	// 所有监听了该时间的监听器执行相应的逻辑。这些监听器监听之后主要做了一件事,就是读取配置文件application.properties,
	// 并把这些信息存储到一个name为applicationConfigurationProperties的属性源中,并将该属性源置于整个属性源列表的最后。

7. 打印banner
        这个主要用来打印图标和版本号,可以自己定制,这里不再解析。
8. 创建ConfigurableApplicationContext

/**
	 * The class name of application context that will be used by default for non-web
	 * environments.
	 */
	public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
			+ "annotation.AnnotationConfigApplicationContext";

	/**
	 * The class name of application context that will be used by default for web
	 * environments.
	 */
	public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."
			+ "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";
	// 主要是为conctextClass赋值,使用了SpringBoot自己的AnnotationConfigEmbeddedWebApplicationContext。
	// 之后通过反射实例化ApplicationContext
	protected ConfigurableApplicationContext createApplicationContext() {
		Class<?> contextClass = this.applicationContextClass;
		if (contextClass == null) {
			try {
				// 如果是web项目读取AnnotationConfigEmbeddedWebApplicationContext值
				contextClass = Class.forName(this.webEnvironment
						? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Unable create a default ApplicationContext, "
								+ "please specify an ApplicationContextClass",
						ex);
			}
		}
		// 通过反射实例化ConfigurableApplicationContext
		return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
	}

9. 准备ConfigurableApplicationContext

private void prepareContext(ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
		// 加载配置
		context.setEnvironment(environment);
		// 传入context
		postProcessApplicationContext(context);
		// (1). 执行初始化器
		applyInitializers(context);
		// 广播该事件
		listeners.contextPrepared(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}

		// Add boot specific singleton beans
		// 添加springApplicationArguments的单例Bean
		context.getBeanFactory().registerSingleton("springApplicationArguments",
				applicationArguments);
		if (printedBanner != null) {
			context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
		}

		// (2).  Load the sources,加载配置
		Set<Object> sources = getSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		load(context, sources.toArray(new Object[sources.size()]));
		listeners.contextLoaded(context);
	}
	// (1). 执行初始化器
	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);
		}
	}
	// (2). 加载配置,其中source参数只包含主类,Application.class
	protected void load(ApplicationContext context, Object[] sources) {
		if (logger.isDebugEnabled()) {
			logger.debug(
					"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
		}
		// 将主类注册到ApplicationContext中
		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();
	}
	// 这里需要注意,在注册到主类时有个校验,是否是Component注解。所以主类要有@Component

10. 刷新ConfigurableApplicationContext

// 调用链过长,这里直接看最终的方法,方法内部注解比较完善
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.准备刷新此Context
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory. 告诉子类刷新内部bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context. 准备bean工厂以便在Context中使用
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses. 允许Context子类中对bean工厂进行后处理
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context. 在Context中调用注册为bean的工厂处理器。
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation. 注册拦截bean创建的bean处理器
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context. Context中初始化消息源
				initMessageSource();

				// Initialize event multicaster for this context.初始化多事件源
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses. 初始化特定的其他特殊bean
				// 该方法创建了一个内嵌的servlet容器,用于执行web应用。默认是创建Tomcat-EmbeddedServletContainer
				onRefresh();

				// Check for listener beans and register them. 检查监听器,并注册
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons. 实例化剩余的所有非延迟加载的单例
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event. 发布refresh finish事件
				// 该方法中发布了ContextRefreshedEvent事件,所有监听了该事件的监听器开始执行,
				// 然后启动Tomcat-EmbeddedServletContainer,启动完成后发布EmbeddedServletContainerInitializedEvent事件,
				// 所有的监听了该事件的监听器开始执行
				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();
			}
		}
	}

11. 容器刷新后动作
  

 // 该方法几乎没做什么事,不做解析了。
    afterRefresh(context, applicationArguments);


    12. SpringApplicationRunListeners发布finish事件
    

// 发布ApplicationReadyEvent或ApplicationFailedEvent事件,所有监听了该事件的监听器执行逻辑。
    listeners.finished(context, null);


    13. 计时器停止计时
    

stopWatch.stop();


    14. 补充步骤。 后期高级版本多了analyzers = new FailureAnalyzers(context);方法。
    // 这个方法就是发初始化的FailureAnalyzer对象,如果是BeanFactoryAware类型的,则调用其setBeanFactory方法,需要注意的是,此时的bean,还没有加载,bean的加载过程还在后面,所以此时获取的beanFactory是没有bean属性的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值