[springboot源码分析]-启动-01

版本

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.13</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

0. 启动类

@SpringBootApplication
public class App {
     public static void main(String[] args) {
//        SpringApplication.run(App.class, args);

        SpringApplication springApplication = new SpringApplication(App.class);
        springApplication.setDefaultProperties(Map.of("name","trump")); // set default properties
        ConfigurableApplicationContext applicationContext = springApplication.run(args);
        applicationContext.registerShutdownHook();
    }
}

1. new SpringApplication(App.class)

public class SpringApplication {

	public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}


	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		//设置resourceLoader,此时为null
		this.resourceLoader = resourceLoader;  //主类, App.class
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));

		//REACTIVE,NONE,默认为SERVLET
		this.webApplicationType = WebApplicationType.deduceFromClasspath();

		//1.1 getSpringFactoriesInstances

		//1.2 
		this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}


	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
		return getSpringFactoriesInstances(type, new Class<?>[] {});
	}

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		//a.若在多个文件中:SpringFactoriesLoader.loadFactories()
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));

		//b. 通过反射,构造instance
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);

		//c. 排序
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

}

1.1 SpringFactoriesLoader

public final class SpringFactoriesLoader {
	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

	public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }

        String factoryTypeName = factoryType.getName();
        return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
    }



    private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
    	Map<String, List<String>> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}
		//a.加载所有的 "META-INF/spring.factories"
		Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			UrlResource resource = new UrlResource(url);
			//b.转换为properties
			Properties properties = PropertiesLoaderUtils.loadProperties(resource);
			for (Map.Entry<?, ?> entry : properties.entrySet()) {
				//c. 读取properties中的每一行, key为factoryTypeName,value 为具体的实现类名称数组
				String factoryTypeName = ((String) entry.getKey()).trim();
				String[] factoryImplementationNames =StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
				for (String factoryImplementationName : factoryImplementationNames) {
					result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>()).add(factoryImplementationName.trim());
				}
			}
		}

		//d. distinct()
		result.replaceAll((factoryType, implementations) -> implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
		cache.put(classLoader, result);
		return result;
	}
}

spring.factories demo

在这里插入图片描述

1.2 关键类

1.2.1 BootstrapRegistryInitializer

接口定义
//package org.springframework.boot;
@FunctionalInterface
public interface BootstrapRegistryInitializer {
	void initialize(BootstrapRegistry registry);
}

1.2.2 ApplicationContextInitializer

接口定义
//package org.springframework.context;
@FunctionalInterface
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
	void initialize(C applicationContext);
}

spring.factories

org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

1.2.3 ApplicationListener

接口定义
//package org.springframework.context;
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
	void onApplicationEvent(E event);

	static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {
		return event -> consumer.accept(event.getPayload());
	}
}

spring.factories

org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener

2.SpringApplication. run()

public class SpringApplication {
	private Set<Class<?>> primarySources; //App.class
	private Class<?> mainApplicationClass;
	private ResourceLoader resourceLoader;
	private WebApplicationType webApplicationType;
	private List<ApplicationContextInitializer<?>> initializers;
	private List<ApplicationListener<?>> listeners;
	private List<BootstrapRegistryInitializer> bootstrapRegistryInitializers;
	
	//DefaultApplicationContextFactory
	private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
	
	//DefaultApplicationStartup
	private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;

	public ConfigurableApplicationContext run(String... args) {
		long startTime = System.nanoTime();
		//2.1 创建DefaultBootstrapContext,  for-each bootstrapRegistryInitializers,执行.initialize() -- 略 
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();

		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();//设置 System.setProperty::"java.awt.headless" 

		//getSpringFactoriesInstances("SpringApplicationRunListener"), 并构造SpringApplicationRunListeners
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//2.2 SpringApplicationRunListeners && SpringApplicationRunListener
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		
		//2.3 @see:SimpleCommandLineArgsParser --- 略
		//获取commandline中的以"--"开头的参数,并以“=”分割,转换为 CommandLineArgs
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

		//2.4
		ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
		configureIgnoreBeanInfo(environment);

		//打印banner-info: 
		Banner printedBanner = printBanner(environment);

		//2.5 
		context = createApplicationContext();
		context.setApplicationStartup(this.applicationStartup);

		//2.6
		prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

		//2.7
		refreshContext(context);

		//2.8
		afterRefresh(context, applicationArguments);

		//2.9 listeners.started()
		Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
		}
		listeners.started(context, timeTakenToStartup);

		//2.10 
		callRunners(context, applicationArguments);
		

		//2.11 listeners.ready()
		Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
		listeners.ready(context, timeTakenToReady);
		return context;
	}
}

2.1 createBootstrapContext() --略

2.2 SpringApplicationRunListeners

2.2.1 SpringApplicationRunListeners

class SpringApplicationRunListeners {
	private final Log log;
	private final List<SpringApplicationRunListener> listeners;
	private final ApplicationStartup applicationStartup;

	SpringApplicationRunListeners(Log log, List<SpringApplicationRunListener> listeners,
			ApplicationStartup applicationStartup) {
		this.log = log;
		this.listeners = List.copyOf(listeners);
		this.applicationStartup = applicationStartup;
	}
	
	//略....
	//
}

2.2.2 SpringApplicationRunListener

定义ConfigurableApplicationContext 各个生命周期的函数。
方法被调用的顺序如接口内方法定义的顺序

public interface SpringApplicationRunListener {
	default void starting(ConfigurableBootstrapContext bootstrapContext) {}
	default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,ConfigurableEnvironment environment) {}
	default void contextPrepared(ConfigurableApplicationContext context) {}
	default void contextLoaded(ConfigurableApplicationContext context) {}
	
	default void started(ConfigurableApplicationContext context, Duration timeTaken) {
		started(context);
	}
	@Deprecated
	default void started(ConfigurableApplicationContext context) {}
	
	default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
		running(context);
	}
	@Deprecated
	default void running(ConfigurableApplicationContext context) {}
	
	default void failed(ConfigurableApplicationContext context, Throwable exception) {}
}

2.2.3 SpringApplicationRunListener 与 ApplicationListener 之间的关系

2.2.3.1 spring.factories:SpringApplicationRunListener默认实现
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

2.2.3.2 EventPublishingRunListener
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {

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

	public EventPublishingRunListener(SpringApplication application, String[] args) {
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();

		//获取所有的 ApplicationListener
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}



	@Override
	public void starting(ConfigurableBootstrapContext bootstrapContext) {
		this.initialMulticaster
			.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
	}

	//.......

	@Override
	public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
		context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context, timeTaken));
		AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
	}
}

2.2.4 listeners.starting() — 略

2.3 ApplicationArguments – 略

读取args[]中,以--key=value形式的参数,构造DefaultApplicationArguments.

2.4 prepareEnvironment()

2.5 createApplicationContext()

protected ConfigurableApplicationContext createApplicationContext() {
	//applicationContextFactory : DefaultApplicationContextFactory
	//webApplicationType: WebApplicationType.SERVLET
	// 返回: AnnotationConfigServletWebServerApplicationContext
	return this.applicationContextFactory.create(this.webApplicationType);
}

DefaultApplicationContextFactory.create()

class DefaultApplicationContextFactory implements ApplicationContextFactory {

	//1.
	@Override
	public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
		//2
		return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,AnnotationConfigApplicationContext::new);
	}

	//2
	private <T> T getFromSpringFactories(WebApplicationType webApplicationType,BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
		//3. load spring.factories 加载org.springframework.boot.ApplicationContextFactory 配置的实现类
		for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,getClass().getClassLoader())) {
			T result = action.apply(candidate, webApplicationType);
			if (result != null) {
				return result;
			}
		}
		return (defaultResult != null) ? defaultResult.get() : null;
	}
}
spring.factories
org.springframework.boot.ApplicationContextFactory=\
org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext.Factory,\
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory

2.6 prepareContext()

public class SpringApplication {

	
	private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
		context.setEnvironment(environment);//设置environment
		postProcessApplicationContext(context); //略



		//1. for-each ApplicationContextInitializer 执行 initializer.initialize(context) --略
		applyInitializers(context);
		listeners.contextPrepared(context);
		bootstrapContext.close(context);
		
		//获取environment中"spring.profiles.active"配置的值,并log


		// Add boot specific singleton beans
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		beanFactory.registerSingleton("springBootBanner", printedBanner);
		//allowCircularReferences , allowBeanDefinitionOverriding
		context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
		// Load the sources
		Set<Object> sources = getAllSources();

		//2.load(context)
		load(context, sources.toArray(new Object[0]));
		listeners.contextLoaded(context);
	}
	
	protected void load(ApplicationContext context, Object[] sources) {
		//2.1  new BeanDefinitionLoader(registry, sources) 
		BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
		loader.setBeanNameGenerator(this.beanNameGenerator);
		loader.setResourceLoader(this.resourceLoader);
		loader.setEnvironment(this.environment);
	
		//2.2 BeanDefinitionLoader.load()
		loader.load();
	}

}

2.6.1 BeanDefinitionLoader.load()

class BeanDefinitionLoader {
	/**
	 * SpringProperties用来加载"spring.properties"文件的配置信息
	 */
	private static final boolean XML_ENABLED = !SpringProperties.getFlag("spring.xml.ignore");

	//2.1 
	BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
		this.sources = sources;
		this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
		this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null);
		this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
		this.scanner = new ClassPathBeanDefinitionScanner(registry);
		this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); //App.class
	}

	//2.2 
	void load() {
		for (Object source : this.sources) {
			// load(Class source) -> this.annotatedReader.register(source) --> AnnotatedBeanDefinitionReader.register
			load(source); 
		}
	}
}

2.6.2 AnnotatedBeanDefinitionReader.register()

public class AnnotatedBeanDefinitionReader {

	public void register(Class<?>... componentClasses) {
		for (Class<?> componentClass : componentClasses) {
			registerBean(componentClass);
		}
	}

	public void registerBean(Class<?> beanClass) {
		doRegisterBean(beanClass, null, null, null, null);
	}


	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {

		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); //App.class

		//1. ConditionEvaluator.shouldSkip #####
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(supplier);
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//略
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//最终 将main().getClass()即App.class 注册到Spring容器。
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

}
2.6.2.1 ConditionEvaluator.shouldSkip()

详情见 https://blog.youkuaiyun.com/it_freshman/article/details/134014949

2.7 refreshContext()

private void refreshContext(ConfigurableApplicationContext context) {
	if (this.registerShutdownHook) {
		//1.SpringApplicationShutdownHook
		shutdownHook.registerApplicationContext(context);
	}
	refresh(context);
}
protected void refresh(ConfigurableApplicationContext applicationContext) {
	applicationContext.refresh();
}

2.7.1 registerShutdownHook.registerApplicationContext(context)

class SpringApplicationShutdownHook implements Runnable {

	private final Handlers handlers = new Handlers();
	private final Set<ConfigurableApplicationContext> contexts = new LinkedHashSet<>();
	private final Set<ConfigurableApplicationContext> closedContexts = Collections.newSetFromMap(new WeakHashMap<>());
	
	
	private final ApplicationContextClosedListener contextCloseListener = new ApplicationContextClosedListener();

	void registerApplicationContext(ConfigurableApplicationContext context) {
		//1.
		addRuntimeShutdownHookIfNecessary();
		synchronized (SpringApplicationShutdownHook.class) {
			assertNotInProgress();
			//99. applicationContext 注册ApplicationContextClosedListener
			context.addApplicationListener(this.contextCloseListener);
			this.contexts.add(context);
		}
	}
	
	//1.
	private void addRuntimeShutdownHookIfNecessary() {
		if (this.shutdownHookAdded.compareAndSet(false, true)) {
			//2
			addRuntimeShutdownHook();
		}
	}
	//2
	void addRuntimeShutdownHook() {
		//3. 当进程关闭时,触发thread.start() ->this.run()
		Runtime.getRuntime().addShutdownHook(new Thread(this, "SpringApplicationShutdownHook"));
	}
	
	//3
	@Override
	public void run() {
		Set<ConfigurableApplicationContext> contexts;
		Set<ConfigurableApplicationContext> closedContexts;
		Set<Runnable> actions;
		synchronized (SpringApplicationShutdownHook.class) {
			this.inProgress = true;
			contexts = new LinkedHashSet<>(this.contexts);
			closedContexts = new LinkedHashSet<>(this.closedContexts);
			actions = new LinkedHashSet<>(this.handlers.getActions());
		}
		//4. 执行close方法
		contexts.forEach(this::closeAndWait);
		closedContexts.forEach(this::closeAndWait);
		//5
		actions.forEach(Runnable::run);
	}
	private void closeAndWait(ConfigurableApplicationContext context) {
		if (!context.isActive()) {
			return;
		}
		//call applicationContext.close()
		context.close();
		
		//等待容器关闭后,方可返回...
		int waited = 0;
		while (context.isActive()) {
			if (waited > TIMEOUT) {
				throw new TimeoutException();
			}
			Thread.sleep(SLEEP);
			waited += SLEEP;
		}
	}
}


//99
private class ApplicationContextClosedListener implements ApplicationListener<ContextClosedEvent> {
	
		//当ContextClosedEvent 事件发生时,触发此方法
		@Override
		public void onApplicationEvent(ContextClosedEvent event) {
			synchronized (SpringApplicationShutdownHook.class) {
				//修改SpringApplicationShutdownHook.contexts,closedContexts 的值
				ApplicationContext applicationContext = event.getApplicationContext();
				SpringApplicationShutdownHook.this.contexts.remove(applicationContext);
				SpringApplicationShutdownHook.this.closedContexts
					.add((ConfigurableApplicationContext) applicationContext);
			}
		}
	}

2.7.2 AnnotationConfigServletWebServerApplicationContext.refresh()

2.8 afterRefresh() – 略

默认为空实现,由子类实现

2.9 listeners.started()—略

2.10 callRunners()

	private void callRunners(ApplicationContext context, ApplicationArguments args) {
		List<Object> runners = new ArrayList<>();
		runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
		runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
		AnnotationAwareOrderComparator.sort(runners);
		for (Object runner : new LinkedHashSet<>(runners)) {
			if (runner instanceof ApplicationRunner) {
				callRunner((ApplicationRunner) runner, args);
			}
			if (runner instanceof CommandLineRunner) {
				callRunner((CommandLineRunner) runner, args);
			}
		}
	}

两者都是在afterRefresh()后被调用,区别是方法的入参不同。

2.10.1ApplicationRunner

@FunctionalInterface
public interface ApplicationRunner {
	/**
	 * Callback used to run the bean.
	 * @param args incoming application arguments
	 */
	void run(ApplicationArguments args) throws Exception;
}

2.10.2 CommandLineRunner

@FunctionalInterface
public interface CommandLineRunner {

	/**
	 * Callback used to run the bean.
	 * @param args incoming main method arguments
	 * @throws Exception on error
	 */
	void run(String... args) throws Exception;

}

2.11 listeners.ready() —略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值