专栏首页earthchen的专栏spring boot自动配置原理

spring boot自动配置原理

spring的4种事务特性,5种隔离级别,7种传播行为

自动配置

想使用自动配置,需要在启动类上添加EnableAutoConfiguration注解,但是一般我们都会在启动类上添加springbootapplication注解,他就包含了自动配置的注解,

自动配置注解代码如下:

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

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

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

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}

这里的关键是使用import注解导入了一个类AutoConfigurationImportSelector

这里给出一个核心的方法

当然这步发生在spring boot启动时run()方法中的refreshContext(context)方法中,也就是在刷新上下文的时候判断当前是否开启了自动配置,如果开启了自动配置就会进入该方法进行自动配置

@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		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 = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return StringUtils.toStringArray(configurations);
	}

这里的关键方法主要是去加载classpath下面的classpath下面的spring.factorties中获取键值对

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;
	}

上述方法调用SpringFactoriesLoader.loadFactoryNames()方法从类路径下得到一个资源

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

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
		String factoryClassName = factoryClass.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryClassName, 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()) {
					List<String> factoryClassNames = Arrays.asList(
							StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
					result.addAll((String) entry.getKey(), factoryClassNames);
				}
			}
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}

扫描javajar包类路径下的“META-INF/spring.factories”这个文件,把这个文件的urls拿到之后并把这些urls每一个遍历,最终把这些文件整成一个properties对象。然后它从properties对象里边获取一些值,把这些获取到的值来加载我们最终要返回的这个结果,这个结果就是我们要交给Spring容器中的所有组件,这相当于这factoryClassName就是我们传过来的Class的这个类名

而这个类名是由getSpringFactoriesLoaderFactoryClass()方法提供

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
		return EnableAutoConfiguration.class;
	}

显而易见,这里的类名为EnableAutoConfiguration.class类名对应的值

读取了spring.factories文件的内容,然后这个文件找到配置所有EnableAutoConfiguration的值加入到Spring容器中

每一个xxxAutoConfiguration类都是容器中的一个组件,并都加入到容器中。

加入到容器中之后的作用就是用它们来做自动配置,这就是Springboot自动配置之源,也就是自动配置的开始,只有这些自动配置类进入到容器中以后,接下来这个自动配置类才开始进行启动

然后就可以按照编写自定义starter的时候的配置文件开始加载了。。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring Boot -- 自动配置原理

    在Spring Boot中自动配置一般使用@EnableXXX方式,Spring默认提供了@EnableAutoConfiguration来配置starter,...

    屈定
  • spring boot自动配置原理

    1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能 ==@EnableAutoConfiguration==

    开源君
  • Spring Boot自动配置原理、实战

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到...

    Java技术栈
  • Spring Boot自动配置原理、实战

    Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射。

    用户5224393
  • 芋道 Spring Boot 自动配置原理

    Spring Boot 自动配置,顾名思义,是希望能够自动配置,将我们从配置的苦海中解脱出来。那么既然要自动配置,它需要解三个问题:

    芋道源码
  • 第5章 Spring Boot自动配置原理

    我们可以看到有783个java文件。spring-boot核心工程有551个java文件。从上面的java文件数量大致可以看出,SpringBoot技术框架的核...

    一个会写诗的程序员
  • 《Spring Boot 实战:从0到1》第4章 Spring Boot自动配置原理第3章 Spring Boot自动配置原理

    我们可以看到有783个java文件。spring-boot核心工程有551个java文件。从上面的java文件数量大致可以看出,SpringBoot技术框架的核...

    一个会写诗的程序员
  • Spring Boot自动配置原理,你必须懂

    小伙伴们是否想起曾经被 SSM 整合支配的恐惧?相信很多小伙伴都是有过这样的经历的,一大堆配置问题,各种排除扫描,导入一个新的依赖又得添加新的配置。自从有了 S...

    南风
  • 《Spring Boot极简教程》第5章 Spring Boot自动配置原理

    我们可以看到有783个java文件。spring-boot核心工程有551个java文件。从上面的java文件数量大致可以看出,SpringBoot技术框架的核...

    一个会写诗的程序员
  • Spring Boot之自动配置原理

    兮动人
  • Spring Boot - 自动配置实现原理

    Spring Boot 中的配置体系是一套强大而复杂的体系,其中最基础、最核心的要数自动配置(AutoConfiguration)机制了。

    小小工匠
  • 五分钟说清楚 Spring Boot的自动配置原理

    Spring Boot没有火起来之前,使用SSM架构的项目那是相当的多,现在也有不少项目还是使用这种架构。在使用SSM架构的时候,大家是否还记得大量配置的烦恼郁...

    田维常
  • Spring Boot核心原理-自动配置

    为什么spring boot能够如此简单的让我们迅速上手。 之前在公司内部推行spring boot时,有同事跟我提到过,感觉换到spring boot这个框...

    于霆霖
  • Spring Boot 自动装配原理

    比如在上面的配置中的spring-boot-starter-web 为我们导入了web环境所需的所有依赖

    LCyee
  • spring 自动配置(中) 自动配置原理

    先看springboot2.0自动注入文件spring.factories如何加载详解 AutoConfigurationImportSelector.jav...

    平凡的学生族
  • Spring Boot 面试杀手锏:自动配置原理

    不论在工作中,亦或是求职面试,Spring Boot已经成为我们必知必会的技能项。除了某些老旧的政府项目或金融项目持有观望态度外,如今的各行各业都在飞速的拥抱这...

    程序IT圈
  • Spring Boot 自动配置

    ○@SpringBootConfiguration:标记当前类为配置类 ○@EnableAutoConfiguration:开启自动配置 ○@Compone...

    赵哥窟
  • Spring Boot的自动配置

    随着Ruby、Groovy等动态语言的流行,相比较之下Java的开发显得格外笨重。繁多的配置、低下的开发效率、复杂的部署流程以及第三方技术集成难度大等问题一直被...

    技术zhai
  • Spring Boot 中的自动配置

    SpringBoot 启动的时候,会有大量的自动配置的类加载到容器中。正是因为 SpringBoot 的这些自动配置,使得我们在编程的时候,不像 Spring ...

    水货程序员

扫码关注云+社区

领取腾讯云代金券