springboot学习之——SpringApplication.run方法

springboot学习之——SpringApplication.run方法

springboot 版本3.1.5

第一步

	/**
	 * Static helper that can be used to run a {@link SpringApplication} from the
	 * specified source using default settings.
	 */
	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}

注释说的啥屁话,这玩意返回一个可配置的应用上下文ConfigurableApplicationContext。看这种名字的类就知道不简单。

run()方法其实创建了一个新的SpringApplication。这个新的SpringApplication会被添加一些属性。

到这里就没了,实例化SpringApplication之后,返回的是更加具体的ConfigurableApplicationContext,也就是说,后面的工作交给了ConfigurableApplicationContext,所以要研究它了。

	/**
	 * Create a new {@link SpringApplication} instance. The application context will load
	 * beans from the specified primary sources (see {@link SpringApplication class-level}
	 * documentation for details). The instance can be customized before calling
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;//null
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//这个资源类就是自己
		this.webApplicationType = WebApplicationType.deduceFromClasspath();//推断使用什么类型的web应用。我们经常用WEBMVC_INDICATOR_CLASS
		this.bootstrapRegistryInitializers = new ArrayList<>(
				getSpringFactoriesInstances(BootstrapRegistryInitializer.class));//启动注册实例化
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//监听器
		this.mainApplicationClass = deduceMainApplicationClass();//主应用类(就是自己项目的启动类)
	}

第二步

ConfigurableApplicationContext

/**
 * SPI interface to be implemented by most if not all application contexts.
 * Provides facilities to configure an application context in addition
 * to the application context client methods in the
 * {@link org.springframework.context.ApplicationContext} interface.
 *
 * <p>Configuration and lifecycle methods are encapsulated here to avoid
 * making them obvious to ApplicationContext client code. The present
 * methods should only be used by startup and shutdown code.
 *
 */
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
	String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
	String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
	String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
	String ENVIRONMENT_BEAN_NAME = "environment";
	String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
	String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
	String APPLICATION_STARTUP_BEAN_NAME = "applicationStartup";
	String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";
    void setId(String id);
	void setParent(@Nullable ApplicationContext parent);
	void setEnvironment(ConfigurableEnvironment environment);
	@Override
	ConfigurableEnvironment getEnvironment();
	void setApplicationStartup(ApplicationStartup applicationStartup);
	ApplicationStartup getApplicationStartup();
	void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
	void addApplicationListener(ApplicationListener<?> listener);
	void removeApplicationListener(ApplicationListener<?> listener);
	void setClassLoader(ClassLoader classLoader);
	void addProtocolResolver(ProtocolResolver resolver);
	void refresh() throws BeansException, IllegalStateException;
	void registerShutdownHook();
	@Override
	void close();
	boolean isActive();
	ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}

SPI接口(串行外设接口,芯片和外设通信用的),实现了大多数应用上下文的SPI接口。注释翻译了结果还是配置应用上下文。

这个类定义了很多程序执行必须的属性和方法。比如环境变量、启动和结束方法等

前面的run()创建了它,程序运行实际是用它来执行的。然而它还是接口,还是要看谁实现了它。

实现它的类也很多。找到一个我们熟悉的看看。AnnotationConfigServletWebApplicationContext

public class AnnotationConfigServletWebApplicationContext extends GenericWebApplicationContext
		implements AnnotationConfigRegistry {
	
	private final AnnotatedBeanDefinitionReader reader;
	private final ClassPathBeanDefinitionScanner scanner;
	private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();
	private String[] basePackages;

	public AnnotationConfigServletWebApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
	public AnnotationConfigServletWebApplicationContext(DefaultListableBeanFactory beanFactory) {
		super(beanFactory);
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
	public AnnotationConfigServletWebApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
		refresh();
	}
	public AnnotationConfigServletWebApplicationContext(String... basePackages) {
		this();
		scan(basePackages);
		refresh();
	}
	@Override
	public void setEnvironment(ConfigurableEnvironment environment) {
		super.setEnvironment(environment);
		this.reader.setEnvironment(environment);
		this.scanner.setEnvironment(environment);
	}
	public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
		this.reader.setBeanNameGenerator(beanNameGenerator);
		this.scanner.setBeanNameGenerator(beanNameGenerator);
		getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
	}
	public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
		this.reader.setScopeMetadataResolver(scopeMetadataResolver);
		this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
	}
	@Override
	public final void register(Class<?>... annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
		this.annotatedClasses.addAll(Arrays.asList(annotatedClasses));
	}
	@Override
	public final void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		this.basePackages = basePackages;
	}
	@Override
	protected void prepareRefresh() {
		this.scanner.clearCache();
		super.prepareRefresh();
	}
	@Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.postProcessBeanFactory(beanFactory);
		if (!ObjectUtils.isEmpty(this.basePackages)) {
			this.scanner.scan(this.basePackages);
		}
		if (!this.annotatedClasses.isEmpty()) {
			this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
		}
	}
	@Override
	public <T> void registerBean(String beanName, Class<T> beanClass, Supplier<T> supplier,
			BeanDefinitionCustomizer... customizers) {
		this.reader.registerBean(beanClass, beanName, supplier, customizers);
	}

}

posted @   繁星TT  阅读(125)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示