当前位置: 首页 > news >正文

Spring源码探析(一):SpringApplication构造函数核心逻辑

作为Spring Boot应用启动的核心入口,SpringApplication.run()方法承载着从‌环境准备‌到‌上下文初始化‌的全流程控制,而SpringApplication的构造函数则是这一流程的‌基石‌。通过解析其构造逻辑,可深入理解Spring Boot如何根据主配置类推断应用类型、加载初始化组件,并为后续的自动装配和上下文构建奠定基础‌。接下来将以该项目中ExcelApplication类开启Spring源码解析之旅。源码跳转

SpringApplication构造函数

	// SpringApplication.run()方法默认调用构造函数,传入配置类
	public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}
	
	// 资源加载器,默认传入null 配置类
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		// 推断应用的web服务类型 NONE(应用服务不作为web服务器使用)SERVLET(作为SERVLET服务器) REACTIVE(作为响应式web服务器)
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		// 从spring.factories获取Bootstrap上下文初始化(BootstrapContext初始化使用)
		this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		// 从spring.factories获取Application上下文初始化(ApplicationContext初始化使用)
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		// 从spring.factories获取ApplicationListener监听器(发布Spring事件的时候使用)
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		// 推断main方法启动类
		this.mainApplicationClass = deduceMainApplicationClass();
	}

    // 获取指定类型spring.factories配置的类实例
    private <T> List<T> getSpringFactoriesInstances(Class<T> type) {
		return getSpringFactoriesInstances(type, null);
	}
   
	private <T> List<T> getSpringFactoriesInstances(Class<T> type, ArgumentResolver argumentResolver) {
		// 获取默认加载文件(spring.factories)的SpringFactoriesLoader来加载类实例 argumentResolver是构造实例时用到的参数
		return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
	}

	// 推断main方法类
    private Class<?> deduceMainApplicationClass() {
    	// StackWalker.Option.RETAIN_CLASS_REFERENCE保留类引用
		return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
		    // 查找main方法class
			.walk(this::findMainClass)
			.orElse(null);
	}

	private Optional<Class<?>> findMainClass(Stream<StackFrame> stack) {
		// 获取方法名字是main的类
		return stack.filter((frame) -> Objects.equals(frame.getMethodName(), "main"))
			.findFirst()
			.map(StackWalker.StackFrame::getDeclaringClass);
	}

推断服务类型

    static WebApplicationType deduceFromClasspath() {
		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
			// 存在DispatcherHandler类且没有DispatcherServlet类和ServletContainer的时候是响应式服务器
			return WebApplicationType.REACTIVE;
		}
		for (String className : SERVLET_INDICATOR_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				// 不存在任何Servlet类的时候
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}

SpringFactoriesLoader加载解析

    // resourceLocation:加载的文件(默认META-INF/spring.factories
    public static SpringFactoriesLoader forResourceLocation(String resourceLocation, @Nullable ClassLoader classLoader) {
		Assert.hasText(resourceLocation, "'resourceLocation' must not be empty");
		ClassLoader resourceClassLoader = (classLoader != null ? classLoader :
				SpringFactoriesLoader.class.getClassLoader());
		// 用类加载器从缓存中获取 不存在新增
		Map<String, SpringFactoriesLoader> loaders = cache.computeIfAbsent(
				resourceClassLoader, key -> new ConcurrentReferenceHashMap<>());
		// 使用加载文件名字从缓存中获取 不存在构建SpringFactoriesLoader
		return loaders.computeIfAbsent(resourceLocation, key ->
				new SpringFactoriesLoader(classLoader, loadFactoriesResource(resourceClassLoader, resourceLocation)));
	}

    // 加载resourceLocation文件中的配置
    protected static Map<String, List<String>> loadFactoriesResource(ClassLoader classLoader, String resourceLocation) {
		Map<String, List<String>> result = new LinkedHashMap<>();
		try {
			// 读取指定目录文件
			Enumeration<URL> urls = classLoader.getResources(resourceLocation);
			while (urls.hasMoreElements()) {
				UrlResource resource = new UrlResource(urls.nextElement());
				// 加载Properties 
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				properties.forEach((name, value) -> {
					// 使用 , 拆分成数组
					String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) value);
					// 使用配置key从map中获取 不存在的时候新增
					List<String> implementations = result.computeIfAbsent(((String) name).trim(),
							key -> new ArrayList<>(factoryImplementationNames.length));
					// trim后添加
                   Arrays.stream(factoryImplementationNames).map(String::trim).forEach(implementations::add);
				});
			}
			// 全部去重替换成不可变list
			result.replaceAll(SpringFactoriesLoader::toDistinctUnmodifiableList);
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" + resourceLocation + "]", ex);
		}
		return Collections.unmodifiableMap(result);
	}

SpringFactoriesLoader加载类实例

    public <T> List<T> load(Class<T> factoryType, @Nullable ArgumentResolver argumentResolver,
			@Nullable FailureHandler failureHandler) {
		Assert.notNull(factoryType, "'factoryType' must not be null");
		// 根据factoryType获取到配置的对应实例类名
		List<String> implementationNames = loadFactoryNames(factoryType);
		logger.trace(LogMessage.format("Loaded [%s] names: %s", factoryType.getName(), implementationNames));
		List<T> result = new ArrayList<>(implementationNames.size());
		// 异常处理 默认抛出异常
		FailureHandler failureHandlerToUse = (failureHandler != null) ? failureHandler : THROWING_FAILURE_HANDLER;
		for (String implementationName : implementationNames) {
			// 实例化类
			T factory = instantiateFactory(implementationName, factoryType, argumentResolver, failureHandlerToUse);
			if (factory != null) {
				result.add(factory);
			}
		}
		// 排序
		AnnotationAwareOrderComparator.sort(result);
		return result;
	}

	protected <T> T instantiateFactory(String implementationName, Class<T> type,
			@Nullable ArgumentResolver argumentResolver, FailureHandler failureHandler) {

		try {
			// 加载类
			Class<?> factoryImplementationClass = ClassUtils.forName(implementationName, this.classLoader);
			Assert.isTrue(type.isAssignableFrom(factoryImplementationClass), () ->
					"Class [%s] is not assignable to factory type [%s]".formatted(implementationName, type.getName()));
			// 用于实例化类的工厂
			FactoryInstantiator<T> factoryInstantiator = FactoryInstantiator.forClass(factoryImplementationClass);
			// 实例化
			return factoryInstantiator.instantiate(argumentResolver);
		}
		catch (Throwable ex) {
			failureHandler.handleFailure(type, implementationName, ex);
			return null;
		}
	}

构建FactoryInstantiator,实例化对应类

    static <T> FactoryInstantiator<T> forClass(Class<?> factoryImplementationClass) {
			// 查找构造方法
		Constructor<?> constructor = findConstructor(factoryImplementationClass);
		Assert.state(constructor != null, () ->
					"Class [%s] has no suitable constructor".formatted(factoryImplementationClass.getName()));
		return new FactoryInstantiator<>((Constructor<T>) constructor);
	}
		
	private static Constructor<?> findConstructor(Class<?> factoryImplementationClass) {
		// Same algorithm as BeanUtils.getResolvableConstructor
		// Kotlin忽略
		Constructor<?> constructor = findPrimaryKotlinConstructor(factoryImplementationClass);
		// 查找public的构造函数 仅有一个的时候获取
		constructor = (constructor != null ? constructor :
					findSingleConstructor(factoryImplementationClass.getConstructors()));
		// 不存在的时候 获取当前类定义的构造方法 仅有一个的时候获取
		constructor = (constructor != null ? constructor :
					findSingleConstructor(factoryImplementationClass.getDeclaredConstructors()));
		// 不存在的时候 获取默认构造函数
		constructor = (constructor != null ? constructor :
					findDeclaredConstructor(factoryImplementationClass));
		return constructor;
	}
	
	// 实例化类
	T instantiate(@Nullable ArgumentResolver argumentResolver) throws Exception {
		// 解析参数 
		Object[] args = resolveArgs(argumentResolver);
		if (isKotlinType(this.constructor.getDeclaringClass())) {
			return KotlinDelegate.instantiate(this.constructor, args);
		}
		// 实例化
		return this.constructor.newInstance(args);
	}
	
	private Object[] resolveArgs(@Nullable ArgumentResolver argumentResolver) {
		// 参数类型
		Class<?>[] types = this.constructor.getParameterTypes();
		return (argumentResolver != null ?
			    // 解析每一个类型对应参数
				Arrays.stream(types).map(argumentResolver::resolve).toArray() :
				// 返回空数组
				new Object[types.length]);
	}

相关文章:

  • 工程化与框架系列(27)--前端音视频处理
  • 用OpenCV写个视频播放器可还行?(C++版)
  • MySQL知识点(第一部分)
  • 深度学习|自监督学习新星:DINO 解析与实践指南
  • 请谈谈 HTTP 中的安全策略,如何防范常见的Web攻击(如XSS、CSRF)?
  • 机器人匹诺曹机制,真话假话平衡机制
  • rpc和proto
  • C++ 算法竞赛STL以及常见模板
  • VMware workstation Pro 17 官网下载教程/安装包
  • 百货店的诞生与现代商业革命:结合开源AI智能客服、AI智能名片与S2B2C商城小程序的新视角
  • [网络爬虫] 动态网页抓取 — Selenium 元素定位
  • 虚幻基础:动画层接口
  • tcp udp区别
  • 【英伟达AI论文】多模态大型语言模型的高效长视频理解
  • STM32 内置的通讯协议
  • 如何监控 Pod 的 CPU/内存使用率,prometheus+grafana
  • Linux内核学习(一)——Vmware虚拟机安装Ubuntu20.4系统及QEMU模拟ARM64 Linux
  • 使用 Python 将 PDF 转换为文本:打造一个简单高效的提取工具
  • 行业案例:10Wtps超高并发“某节跳动”钱包架构与落地方案
  • 【论文精读】GaussReg: Fast 3D Registration with Gaussian Splatting
  • 80后女博士黄双燕拟提名为内蒙古盟市政府(行署)副职人选
  • 女孩患异食癖爱吃头发,一年后腹痛入院体内惊现“头发巨石”
  • 全国人大常委会今年将初次审议检察公益诉讼法
  • 人民日报仲音:大力纠治违规吃喝顽瘴痼疾
  • 北京今日白天超30℃晚间下冰雹,市民称“没见过这么大颗的”
  • 习近平同巴西总统卢拉共同会见记者