SpringBoot启动原理与源码解读


程序入库

源码如下:

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

一、@SpringBootApplication

  1. 完成了SpringBootConfiguration
  2. 完成了EnableAutoConfiguration中的自动配置
  3. 通过ComponentScan完成扫描
    源码如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
//扫描的时候去除掉下面的过滤器
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {};

    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "nameGenerator"
    )
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

1.1 @SpringBootConfiguration

代理Bean方法为true。其中我们知道代码分为JAVA动态代理和CGLB代码两种代理情况。

原代码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {

	/**
	 * 动态代理Bean方法为ture
	 */
	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;

}

1.2 @EnableAutoConfiguration

  1. AutoConfigurationPackage完成当前包下的配置信息
  2. AutoConfigurationImportSelector完成自动配置导入选择器,完成需要导入的类选择。

启动Spring应用上下文自动配置,参数猜想去配置你可能需要的Beans。
自动配置类通常基于类路径和定义的Bean来应用。
当使用SpringBootApplication,自动启动自动配置上下文,因此添加此注解不会产生额外的效果。
自动配置尝试尽可能智能化,并在您定义了更多自己的配置时退出自动配置值。
你可以随时手动配置任何您不想要的配置通过excludeName(),如果没有访问此方法(excludeName())权限,您也可以通过spring.autoconfigure.exclude属性。自动配置总是应用于用户定义beans注册之后。
在包下类使用注册EnableAutoConfiguration,通常基于SpringBootApplication。具有特定意义通常采用·default·。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	/**
	 * Environment property that can be used to override when auto-configuration is enabled.
	 */
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 */
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 */
	String[] excludeName() default {};

}

1.2.1 AutoConfigurationPackage

  1. 返回需要自动配置包的名称
  2. 通过AutoConfigurationPackages.Registrar这个方法返回需要注册的包
  3. 说明Import会自动将当前类添加到Bean中

源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

	/**
	 * 基础名称数组
	 */
	String[] basePackages() default {};

	/**
	 * 基础包类数组
	 */
	Class<?>[] basePackageClasses() default {};
}
1.1.1.1 AutoConfigurationPackages.Registrar

源码如下:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
		register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
	}

	@Override
	public Set<Object> determineImports(AnnotationMetadata metadata) {
		return Collections.singleton(new PackageImports(metadata));
	}

}
1.1.1.2 PackageImports
  1. 包名导入,看是否配置了basePackage的包名、配置了basePackageClass的包下类名称。

代码如下:

PackageImports(AnnotationMetadata metadata) {
	AnnotationAttributes attributes = AnnotationAttributes
					.fromMap(metadata.getAnnotationAttributes(AutoConfigurationPackage.class.getName(), false));
	List<String> packageNames = new ArrayList<>();
	for (String basePackage : attributes.getStringArray("basePackages")) {
		packageNames.add(basePackage);
	}
	for (Class<?> basePackageClass : attributes.getClassArray("basePackageClasses")) {
		packageNames.add(basePackageClass.getPackage().getName());
	}
	if (packageNames.isEmpty()) {
		packageNames.add(ClassUtils.getPackageName(metadata.getClassName()));
	}
	this.packageNames = Collections.unmodifiableList(packageNames);
}

一般获得的自动导入包名称为当前启动类的包名称:

public static String getPackageName(String fqClassName) {
	Assert.notNull(fqClassName, "Class name must not be null");
	int lastDotIndex = fqClassName.lastIndexOf(PACKAGE_SEPARATOR);
	return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : "");
}

1.2.2 AutoConfigurationImportSelector

1 通过selectImports来获得选择需要导入的自动配置类
2 通过getAutoConfigurationEntry来完成第一步中获取SpringBoot自动配置入库类。
3 通过getAttributes方法获取注解元数据的属性
4 通过getCandidateConfigurations来获取自动配置类读取的文件是当前应用所有依赖的第三方ja下META-INF/spring.factories这个文件内容。
5. 通过removeDuplicates移除重复的类名称。
6. 通过getExclusions来获得需要排除的类。
7. 通过checkExcludedClasses来检查需要排除的类是否正确。
8. 在自动配置类中去除掉需要排除类。
9. 通过getConfigurationClassFilter来获得(META-INF/spring-autoconfigure-metadata.properties)中的自动配置元数据,过滤器匹配自动配置元数据和自动配置类相关内容。
10. 通过fireAutoConfigurationImportEvents来消除自动配置导入事件。

重要代码

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return NO_IMPORTS;
	}
	AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
	return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
//获取自动配置类入口
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
	}
	AnnotationAttributes attributes = getAttributes(annotationMetadata);
	List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
	configurations = removeDuplicates(configurations);
	Set<String> exclusions = getExclusions(annotationMetadata, attributes);
	checkExcludedClasses(configurations, exclusions);
	configurations.removeAll(exclusions);
	configurations = getConfigurationClassFilter().filter(configurations);
	fireAutoConfigurationImportEvents(configurations, exclusions);
	return new AutoConfigurationEntry(configurations, exclusions);
}

getCandidateConfigurations重要代码解读获取自动配置类名称

//获取候选配置类名称
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
	Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
	return configurations;
}
//通过加载工厂获取自动配置类名称
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
	String factoryTypeName = factoryType.getName();
	return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
//加载"META-INF/spring.factories中的数据,根据classLoader当前对象所处程序所有依赖jar的资源。
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
	MultiValueMap<String, String> result = cache.get(classLoader);
	if (result != null) {
		return result;
	}

	try {
		Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
		result = new LinkedMultiValueMap<>();
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			UrlResource resource = new UrlResource(url);
			Properties properties = PropertiesLoaderUtils.loadProperties(resource);
			for (Map.Entry<?, ?> entry : properties.entrySet()) {
				String factoryTypeName = ((String) entry.getKey()).trim();
				for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
					result.add(factoryTypeName, factoryImplementationName.trim());
				}
			}
		}
		cache.put(classLoader, result);
		return result;
	}
	catch (IOException ex) {
		throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
	}
}

getConfigurationClassFilter来获取自动配置需要满足的信息META-INF/spring-autoconfigure-metadata.properties

//获取配置类过滤器
private ConfigurationClassFilter getConfigurationClassFilter() {
	if (this.configurationClassFilter == null) {
		List<AutoConfigurationImportFilter> filters = getAutoConfigurationImportFilters();
		for (AutoConfigurationImportFilter filter : filters) {
			invokeAwareMethods(filter);
		}
		this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);
	}
	return this.configurationClassFilter;
}
ConfigurationClassFilter(ClassLoader classLoader, List<AutoConfigurationImportFilter> filters) {
    //获得自动配置类元数据
	this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(classLoader);
	//自动配置导入过滤器
	this.filters = filters;
}
//过滤掉在自动配置类元数据中不存在的类名称
List<String> filter(List<String> configurations) {
	long startTime = System.nanoTime();
	String[] candidates = StringUtils.toStringArray(configurations);
	boolean skipped = false;
	for (AutoConfigurationImportFilter filter : this.filters) {
		boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
		for (int i = 0; i < match.length; i++) {
			if (!match[i]) {
				candidates[i] = null;
				skipped = true;
			}
		}
	}
	if (!skipped) {
		return configurations;
	}
	List<String> result = new ArrayList<>(candidates.length);
	for (String candidate : candidates) {
		if (candidate != null) {
			result.add(candidate);
		}
	}
	if (logger.isTraceEnabled()) {
		int numberFiltered = configurations.size() - result.size();
		logger.trace("Filtered " + numberFiltered + " auto configuration class in "
						+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
	}
	return result;
}
//根据路径获取自动配置元数据 
//PATH = "META-INF/spring-autoconfigure-metadata.properties"
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
	return loadMetadata(classLoader, PATH);
}

static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
	try {
		Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
					: ClassLoader.getSystemResources(path);
		Properties properties = new Properties();
		while (urls.hasMoreElements()) {
			properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
		}
		return loadMetadata(properties);
	}
	catch (IOException ex) {
		throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);
	}
}

二、SpringApplication

  1. SpringApplication应用上下文配置
  2. run启动
 */
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
	return run(new Class<?>[] { primarySource }, args);
}

/**
* 配置应用上下文
*/
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
	return new SpringApplication(primarySources).run(args);
}

初始化SpringApplication

WebApplicationType
NONE:不是一个WEB应用
SERVLET:是以Servlet的WEB应用程序
REACTIVE:是以Reactive的WEB应用程序

setInitializers:会设置初始化类

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

setListeners 设置监听类

org.springframework.boot.ClearCachesApplicationListener,
org.springframework.boot.builder.ParentContextCloserApplicationListener,
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,
org.springframework.boot.context.FileEncodingApplicationListener,
org.springframework.boot.context.config.AnsiOutputApplicationListener,
org.springframework.boot.context.config.ConfigFileApplicationListener,
org.springframework.boot.context.config.DelegatingApplicationListener,
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,
org.springframework.boot.context.logging.LoggingApplicationListener,
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
ConfigFileApplicationListener会自动搜索classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/这些目录

详情参考spring-boot.jar目录下META-INF/spring.factories

/**
 * 创建一个SpringApplication实例
 */
public SpringApplication(Class<?>... primarySources) {
	this(null, primarySources);
}

/**
 * 创建一个SpringApplication实例
 * 判断Web应用类型
 * 
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
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应用程序类型:一般为SERVERL
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	//设置初始化实例对象来自于读取ApplicationContextInitializer类所在jar下META-INF/spring.factories文件
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	//设置监听实例对象来自于读取ApplicationListener类所在jar下META-INF/spring.factories文件
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	//
	this.mainApplicationClass = deduceMainApplicationClass();
}
//推动Main方法应用程序类
private Class<?> deduceMainApplicationClass() {
	try {
		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;
}

getSpringFactoriesInstances获取Spring工厂实例

  1. 其中SpringFactoriesLoader.loadFactoryNames(type, classLoader)是读取classLoader类所在jar下的META-INF/spring.factories文件信息
  2. 其中createSpringFactoriesInstances创建获取到的类名称,进行初始化实例。
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
	ClassLoader classLoader = getClassLoader();
	// Use names and ensure unique to protect against duplicates
	Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
	List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
	AnnotationAwareOrderComparator.sort(instances);
	return instances;
}
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
			ClassLoader classLoader, Object[] args, Set<String> names) {
	List<T> instances = new ArrayList<>(names.size());
	for (String name : names) {
		try {
		    //获取当前类
			Class<?> instanceClass = ClassUtils.forName(name, classLoader);
			Assert.isAssignable(type, instanceClass);
			//获取类的构造方法
			Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
			//执行构造方法获得实例
			T instance = (T) BeanUtils.instantiateClass(constructor, args);
			instances.add(instance);
			}
		catch (Throwable ex) {
			throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
		}
	}
	return instances;
}

run方法执行

public ConfigurableApplicationContext run(String... args) {
	//记时间秒表
	StopWatch stopWatch = new StopWatch();
	//启动秒表
	stopWatch.start();
	//配置应用上下文
	ConfigurableApplicationContext context = null;
	//配置头属性是否缺失
	configureHeadlessProperty();
	//获取Spring应用运行监听类
	SpringApplicationRunListeners listeners = getRunListeners(args);
	//监听开始
	listeners.starting();
	try {
		//应用参数,可以传入特殊字符串如:--参数1,或是--key1=value1,或是参数1
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		//准备应用环境
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
		//配置忽略bean信息到环境中
		configureIgnoreBeanInfo(environment);
		//在启动台打印Banner
		Banner printedBanner = printBanner(environment);
		//创建应用上下文:根据WEB类型创建不同的应用上下文
		context = createApplicationContext();
		//准备上下文
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
		//刷新上下文: 因为在准备上下文时候初始化了一些信息需要重新载入Context
		refreshContext(context);
		//刷新上下文件之后:该方法未实现
		afterRefresh(context, applicationArguments);
		//计时秒表停止
		stopWatch.stop();
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
		}
		//监听器开始监听上下文
		listeners.started(context);
		//运行ApplicationRunner类和CommandLineRunner类。
		callRunners(context, applicationArguments);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, listeners);
		throw new IllegalStateException(ex);
	}

	try {
		listeners.running(context);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, null);
		throw new IllegalStateException(ex);
	}
	return context;
}

getRunListeners(获得运行监听类)

读取SpringApplicationRunListener类jar下的META-INF/spring.factories文件中类名称。

Spring应用上下文运行监听类

private SpringApplicationRunListeners getRunListeners(String[] args) {
	Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
	return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}

prepareEnvironment(准备环境)

  1. getOrCreateEnvironment中根据WEB应用类型创建或获取到对应类型的环境配置。

准备环境

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
	// Create and configure the environment
	ConfigurableEnvironment environment = getOrCreateEnvironment();
	//配置环境
	configureEnvironment(environment, applicationArguments.getSourceArgs());
	ConfigurationPropertySources.attach(environment);
	//监听器环境准备
	listeners.environmentPrepared(environment);
	//将环境绑定到Spring应用
	bindToSpringApplication(environment);
	if (!this.isCustomEnvironment) {
		environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
	}
	ConfigurationPropertySources.attach(environment);
	return environment;
}

printBanner(打印横幅)

private Banner printBanner(ConfigurableEnvironment environment) {
	if (this.bannerMode == Banner.Mode.OFF) {
		return null;
	}
	//资源加载器
	ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
				: new DefaultResourceLoader(null);
	//Spring应用横幅打印
	SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
	if (this.bannerMode == Mode.LOG) {
		return bannerPrinter.print(environment, this.mainApplicationClass, logger);
	}
	//打印横幅
	return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}

SpringApplicationBannerPrinter(ResourceLoader resourceLoader, Banner fallbackBanner) {
	this.resourceLoader = resourceLoader;
	this.fallbackBanner = fallbackBanner;
}
//打印横幅
Banner print(Environment environment, Class<?> sourceClass, Log logger) {
	Banner banner = getBanner(environment);
	try {
		logger.info(createStringFromBanner(banner, environment, sourceClass));
	}
	catch (UnsupportedEncodingException ex) {
			logger.warn("Failed to create String for banner", ex);
	}
	return new PrintedBanner(banner, sourceClass);
}

Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
	Banner banner = getBanner(environment);
	banner.printBanner(environment, sourceClass, out);
	return new PrintedBanner(banner, sourceClass);
}
//获取横幅,其中默认的SpringBoot,其他的自己配置
//图片横幅:在设置的时候key为spring.banner.image.location,支持类型"gif", "jpg", "png"
//字体横幅:在设置的时候key为spring.banner.location,支持类型txt文本。
private Banner getBanner(Environment environment) {
	Banners banners = new Banners();
	banners.addIfNotNull(getImageBanner(environment));
	banners.addIfNotNull(getTextBanner(environment));
	if (banners.hasAtLeastOneBanner()) {
		return banners;
	}
	if (this.fallbackBanner != null) {
		return this.fallbackBanner;
	}
	return DEFAULT_BANNER;
}

prepareContext(准备上下文)

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
			SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
	//将环境信息设置当上下文中
	context.setEnvironment(environment);
	//前置流程中会初始化默认:beanNameGenerator、resourceLoader、ConversionService实例
	postProcessApplicationContext(context);
	//应用初始设定
	//在创建SpringApplication的时候,已经设置了需要初始化的类。将上下文件初始化到初始化类中。
	applyInitializers(context);
	//监听 准备上下文
	listeners.contextPrepared(context);
	if (this.logStartupInfo) {
		logStartupInfo(context.getParent() == null);
		logStartupProfileInfo(context);
	}
	// Add boot specific singleton beans
	//获取上下文中的Bean工厂
	ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
	//Bean工厂注册单例:应用参数注册为单例
	beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
	//是否准备打印横幅
	if (printedBanner != null) {
		//注册打印横幅为单例
		beanFactory.registerSingleton("springBootBanner", printedBanner);
	}
	//如果Bean工厂,存在父类为DefaultListableBeanFactory
	//设置允许Bean解析覆盖
	if (beanFactory instanceof DefaultListableBeanFactory) {
		((DefaultListableBeanFactory) beanFactory)
					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
	}
	//懒加载初始化:上下文件添加Bean工厂后置处理器为LazyInitializationBeanFactoryPostProcessor
	if (this.lazyInitialization) {
		context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
	}
	// Load the sources
	Set<Object> sources = getAllSources();
	Assert.notEmpty(sources, "Sources must not be empty");
	load(context, sources.toArray(new Object[0]));
	listeners.contextLoaded(context);
}

load(加载资源)

//在加载资源时会设置beanNameGenerator、resourceLoader、environment
protected void load(ApplicationContext context, Object[] sources) {
	if (logger.isDebugEnabled()) {
			logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
	}
	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();
}
//其中loader.load()加载下面方法
int load() {
	int count = 0;
	for (Object source : this.sources) {
		count += load(source);
	}
	return count;
}
//加载了对应的资源后,会返回当前加载资源数量
private int load(Object source) {
	Assert.notNull(source, "Source must not be null");
	if (source instanceof Class<?>) {
		return load((Class<?>) source);
	}
	if (source instanceof Resource) {
		return load((Resource) source);
	}
	if (source instanceof Package) {
		return load((Package) source);
	}
	if (source instanceof CharSequence) {
		return load((CharSequence) source);
	}
	throw new IllegalArgumentException("Invalid source type " + source.getClass());
}

总结

  1. ClassLoader:
  1. packages包含当前运行程序所有第三方依赖jar。
  2. path:包含当前应用的位置以及所有第三方jar的存储位置。
  1. 自动加载到所有第三方jar中的"META-INF/spring.factories"
  1. 通过资源加载器,加载到文件中的信息。
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
		String factoryTypeName = factoryType.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
	}

	private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		try {
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					String factoryTypeName = ((String) entry.getKey()).trim();
					for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
						result.add(factoryTypeName, factoryImplementationName.trim());
					}
				}
			}
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值