SpringBoot启动过程核心源码解析
2022-05-23 17:33:00 7 举报
AI智能生成
SpringBoot启动过程核心源码解析
作者其他创作
大纲/内容
应用入口
@SpringBootApplication<br>public class Application {<br> public static void main(String[] args) {<br> SpringApplication.run(Application.class, args);<br> }<br>}
解析SpringApplication
public ConfigurableApplicationContext run(String... args)
StopWatch stopWatch = new StopWatch();<br>stopWatch.start();
SpringApplicationRunListeners listeners = getRunListeners(args);
private SpringApplicationRunListeners getRunListeners(String[] args) {<br> Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };<br> return new SpringApplicationRunListeners(logger,<br> getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));<br> }
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {<br> ClassLoader classLoader = getClassLoader();<br> // Use names and ensure unique to protect against duplicates<br> Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));<br> List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);<br> AnnotationAwareOrderComparator.sort(instances);<br> return instances;<br> }
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {<br> String factoryTypeName = factoryType.getName();<br> return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());<br> }
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {<br> MultiValueMap<String, String> result = cache.get(classLoader);<br> if (result != null) {<br> return result;<br> }<br><br> try {<br> Enumeration<URL> urls = (classLoader != null ?<br> classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :<br> ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));<br> result = new LinkedMultiValueMap<>();<br> while (urls.hasMoreElements()) {<br> URL url = urls.nextElement();<br> UrlResource resource = new UrlResource(url);<br> Properties properties = PropertiesLoaderUtils.loadProperties(resource);<br> for (Map.Entry<?, ?> entry : properties.entrySet()) {<br> String factoryTypeName = ((String) entry.getKey()).trim();<br> for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {<br> result.add(factoryTypeName, factoryImplementationName.trim());<br> }<br> }<br> }<br> cache.put(classLoader, result);<br> return result;<br> }<br> catch (IOException ex) {<br> throw new IllegalArgumentException("Unable to load factories from location [" +<br> FACTORIES_RESOURCE_LOCATION + "]", ex);<br> }<br> }
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,<br> ClassLoader classLoader, Object[] args, Set<String> names) {<br> List<T> instances = new ArrayList<>(names.size());<br> for (String name : names) {<br> try {<br> Class<?> instanceClass = ClassUtils.forName(name, classLoader);<br> Assert.isAssignable(type, instanceClass);<br> Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);<br> T instance = (T) BeanUtils.instantiateClass(constructor, args);<br> instances.add(instance);<br> }<br> catch (Throwable ex) {<br> throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);<br> }<br> }<br> return instances;<br> }
listeners.start();
void starting() {<br> for (SpringApplicationRunListener listener : this.listeners) {<br> listener.starting();<br> }<br> }
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {<br> ......<br>@Override<br> public void starting() {<br> this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));<br> }<br> ......<br>}
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
public class DefaultApplicationArguments implements ApplicationArguments {<br><br> private final Source source;<br><br> private final String[] args;<br><br> public DefaultApplicationArguments(String... args) {<br> Assert.notNull(args, "Args must not be null");<br> this.source = new Source(args);<br> this.args = args;<br> }<br>}
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);<br>
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,<br> ApplicationArguments applicationArguments) {<br> // Create and configure the environment<br> ConfigurableEnvironment environment = getOrCreateEnvironment();<br> configureEnvironment(environment, applicationArguments.getSourceArgs());<br> ConfigurationPropertySources.attach(environment);<br> listeners.environmentPrepared(environment);<br> bindToSpringApplication(environment);<br> if (!this.isCustomEnvironment) {<br> environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,<br> deduceEnvironmentClass());<br> }<br> ConfigurationPropertySources.attach(environment);<br> return environment;<br> }
private ConfigurableEnvironment getOrCreateEnvironment() {<br> if (this.environment != null) {<br> return this.environment;<br> }<br> switch (this.webApplicationType) {<br> case SERVLET:<br> return new StandardServletEnvironment();<br> case REACTIVE:<br> return new StandardReactiveWebEnvironment();<br> default:<br> return new StandardEnvironment();<br> }<br> }
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {<br> if (this.addConversionService) {<br> ConversionService conversionService = ApplicationConversionService.getSharedInstance();<br> environment.setConversionService((ConfigurableConversionService) conversionService);<br> }<br> configurePropertySources(environment, args);<br> configureProfiles(environment, args);<br> }
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {<br> MutablePropertySources sources = environment.getPropertySources();<br> if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {<br> sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));<br> }<br> if (this.addCommandLineProperties && args.length > 0) {<br> String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;<br> if (sources.contains(name)) {<br> PropertySource<?> source = sources.get(name);<br> CompositePropertySource composite = new CompositePropertySource(name);<br> composite.addPropertySource(<br> new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));<br> composite.addPropertySource(source);<br> sources.replace(name, composite);<br> }<br> else {<br> sources.addFirst(new SimpleCommandLinePropertySource(args));<br> }<br> }<br> }
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {<br> Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);<br> profiles.addAll(Arrays.asList(environment.getActiveProfiles()));<br> environment.setActiveProfiles(StringUtils.toStringArray(profiles));<br> }
public final class ConfigurationPropertySources {<br>public static void attach(Environment environment) {<br> Assert.isInstanceOf(ConfigurableEnvironment.class, environment);<br> MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();<br> PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);<br> if (attached != null && attached.getSource() != sources) {<br> sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);<br> attached = null;<br> }<br> if (attached == null) {<br> sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,<br> new SpringConfigurationPropertySources(sources)));<br> }<br> }<br>}
class SpringApplicationRunListeners {<br>void environmentPrepared(ConfigurableEnvironment environment) {<br> for (SpringApplicationRunListener listener : this.listeners) {<br> listener.environmentPrepared(environment);<br> }<br> }<br>}
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {<br>@Override<br> public void environmentPrepared(ConfigurableEnvironment environment) {<br> this.initialMulticaster<br> .multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));<br> }<br>}
protected void bindToSpringApplication(ConfigurableEnvironment environment) {<br> try {<br> Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));<br> }<br> catch (Exception ex) {<br> throw new IllegalStateException("Cannot bind to SpringApplication", ex);<br> }<br> }
configureIgnoreBeanInfo(environment);<br>
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {<br> if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {<br> Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);<br> System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());<br> }<br> }
Banner printedBanner = printBanner(environment);<br>
private Banner printBanner(ConfigurableEnvironment environment) {<br> if (this.bannerMode == Banner.Mode.OFF) {<br> return null;<br> }<br> ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader<br> : new DefaultResourceLoader(null);<br> SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);<br> if (this.bannerMode == Mode.LOG) {<br> return bannerPrinter.print(environment, this.mainApplicationClass, logger);<br> }<br> return bannerPrinter.print(environment, this.mainApplicationClass, System.out);<br> }
ConfigurableApplicationContext context = createApplicationContext();<br>
protected ConfigurableApplicationContext createApplicationContext() {<br> Class<?> contextClass = this.applicationContextClass;<br> if (contextClass == null) {<br> try {<br> switch (this.webApplicationType) {<br> case SERVLET:<br> contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);<br> break;<br> case REACTIVE:<br> contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);<br> break;<br> default:<br> contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);<br> }<br> }<br> catch (ClassNotFoundException ex) {<br> throw new IllegalStateException(<br> "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);<br> }<br> }<br> return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);<br> }
prepareContext(context, environment, listeners, applicationArguments, printedBanner);<br>
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,<br> SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {<br> context.setEnvironment(environment);<br> postProcessApplicationContext(context);<br> applyInitializers(context);<br> listeners.contextPrepared(context);<br> if (this.logStartupInfo) {<br> logStartupInfo(context.getParent() == null);<br> logStartupProfileInfo(context);<br> }<br> // Add boot specific singleton beans<br> ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();<br> beanFactory.registerSingleton("springApplicationArguments", applicationArguments);<br> if (printedBanner != null) {<br> beanFactory.registerSingleton("springBootBanner", printedBanner);<br> }<br> if (beanFactory instanceof DefaultListableBeanFactory) {<br> ((DefaultListableBeanFactory) beanFactory)<br> .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);<br> }<br> if (this.lazyInitialization) {<br> context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());<br> }<br> // Load the sources<br> Set<Object> sources = getAllSources();<br> Assert.notEmpty(sources, "Sources must not be empty");<br> load(context, sources.toArray(new Object[0]));<br> listeners.contextLoaded(context);<br> }
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {<br> if (this.beanNameGenerator != null) {<br> context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,<br> this.beanNameGenerator);<br> }<br> if (this.resourceLoader != null) {<br> if (context instanceof GenericApplicationContext) {<br> ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);<br> }<br> if (context instanceof DefaultResourceLoader) {<br> ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());<br> }<br> }<br> if (this.addConversionService) {<br> context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());<br> }<br> }
protected void applyInitializers(ConfigurableApplicationContext context) {<br> for (ApplicationContextInitializer initializer : getInitializers()) {<br> Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),<br> ApplicationContextInitializer.class);<br> Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");<br> initializer.initialize(context);<br> }<br> }
class SpringApplicationRunListeners {<br>void contextPrepared(ConfigurableApplicationContext context) {<br> for (SpringApplicationRunListener listener : this.listeners) {<br> listener.contextPrepared(context);<br> }<br> }<br>}
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {<br>@Override<br> public void contextPrepared(ConfigurableApplicationContext context) {<br> this.initialMulticaster<br> .multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));<br> }<br>}
protected void load(ApplicationContext context, Object[] sources) {<br> if (logger.isDebugEnabled()) {<br> logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));<br> }<br> BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);<br> if (this.beanNameGenerator != null) {<br> loader.setBeanNameGenerator(this.beanNameGenerator);<br> }<br> if (this.resourceLoader != null) {<br> loader.setResourceLoader(this.resourceLoader);<br> }<br> if (this.environment != null) {<br> loader.setEnvironment(this.environment);<br> }<br> loader.load();<br> }
class SpringApplicationRunListeners {<br>void contextLoaded(ConfigurableApplicationContext context) {<br> for (SpringApplicationRunListener listener : this.listeners) {<br> listener.contextLoaded(context);<br> }<br> }<br>}
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {<br>@Override<br> public void contextLoaded(ConfigurableApplicationContext context) {<br> for (ApplicationListener<?> listener : this.application.getListeners()) {<br> if (listener instanceof ApplicationContextAware) {<br> ((ApplicationContextAware) listener).setApplicationContext(context);<br> }<br> context.addApplicationListener(listener);<br> }<br> this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));<br> }<br>}
refreshContext(context);<br>
private void refreshContext(ConfigurableApplicationContext context) {<br> refresh((ApplicationContext) context);<br> if (this.registerShutdownHook) {<br> try {<br> context.registerShutdownHook();<br> }<br> catch (AccessControlException ex) {<br> // Not allowed in some environments.<br> }<br> }<br> }
protected void refresh(ConfigurableApplicationContext applicationContext) {<br> applicationContext.refresh();<br> }
afterRefresh(context, applicationArguments);<br>
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {<br> }
stopWatch.stop();<br>
listeners.started(context);<br>
class SpringApplicationRunListeners {<br>void started(ConfigurableApplicationContext context) {<br> for (SpringApplicationRunListener listener : this.listeners) {<br> listener.started(context);<br> }<br> }<br>}
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {<br>@Override<br> public void started(ConfigurableApplicationContext context) {<br> context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));<br> AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);<br> }<br>}
callRunners(context, applicationArguments);<br>
private void callRunners(ApplicationContext context, ApplicationArguments args) {<br> List<Object> runners = new ArrayList<>();<br> runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());<br> runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());<br> AnnotationAwareOrderComparator.sort(runners);<br> for (Object runner : new LinkedHashSet<>(runners)) {<br> if (runner instanceof ApplicationRunner) {<br> callRunner((ApplicationRunner) runner, args);<br> }<br> if (runner instanceof CommandLineRunner) {<br> callRunner((CommandLineRunner) runner, args);<br> }<br> }<br> }
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {<br> try {<br> (runner).run(args);<br> }<br> catch (Exception ex) {<br> throw new IllegalStateException("Failed to execute ApplicationRunner", ex);<br> }<br> }
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {<br> try {<br> (runner).run(args.getSourceArgs());<br> }<br> catch (Exception ex) {<br> throw new IllegalStateException("Failed to execute CommandLineRunner", ex);<br> }<br> }
listeners.running(context);<br>
class SpringApplicationRunListeners {<br>void running(ConfigurableApplicationContext context) {<br> for (SpringApplicationRunListener listener : this.listeners) {<br> listener.running(context);<br> }<br> }<br>}
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {<br>@Override<br> public void running(ConfigurableApplicationContext context) {<br> context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));<br> AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);<br> }<br>}
0 条评论
下一页