SpringBoot自动配置原理

简介

不知道大家还记不记得第一次搭建SpringBoot环境的时候,有没有觉得非常简单,非常方便,无须各种的配置文件,无需各种繁杂的pom坐标,一个main方法,就能run起来了.与其他的框架整合也狠方便,再启动类上加一个EnableXXX就可以了.今天看一下SpringBoot是如何实现自动配置的
源码的话就先送启动类入手:

@SpringBootApplication
public class DemoApplication {

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

}

@SpringBootApplication:SpringBoot应用中,这个注解标注再那个类上,就说明这个类是当前应用的主配置类,SpringBoot需要运行主配置类的main方法来启动SpringBoot应用

  • SpringBootApplication
//设置当前注解可以标注在哪
@Target(ElementType.TYPE)
//当前注解标注的类编译以什么方式保留
//RetentionPolicy.RUNTIME::会被java虚拟机所加载
@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 {
		//...
}
  • @SpringBootApplication是一个组合注解,上面包含着三个注解
  1. SpringBootConfiguration:标注再某个类上,这个类就是SpringBoot的配置类;SpringBootConfiguration类上只有一个注解@Configuration,作用等同于Configuration;
  2. @EnableAutoConfiguration:开启自动配置,以前我们需要配置的东西,现在SpringBoot可以帮我们去配置,@EnableAutoConfiguration告诉SpringBoot开启自动配置,SpringBoot会自动帮我们去加载自动配置类
  3. @ComponentScan:相当于Spring.xml文件中context:comonent-scan,但是没有指定basePackage,如果没有指定当前的扫描包,SpringBoot会默认扫描启动类所再的包下的所有类(含子包下的类)

TypeExcludeFilter:这个是SpringBoot对外提供的扩展类,可以供我们去按照自己的方式进行排除
AutoConfigurationExcludeFilter:排除所有的配置类并且是自动配置类里面的其中一个

  • @EnableAutoConfiguration
    这个注解是@SpringBootApplication中的重中之重,如此见名知意的名字,一看就知道SpringBoot要开始操作了,于是默默点进EnableAutoConfiguration的源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//将当前配置类所在的包保存再BasePackage的Bean中,供Spring内部使用
@AutoConfigurationPackage
//完成导入配置功能
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	//...
}
  • @AutoConfigurationPackage
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//保存扫描路径;就是注册了一个保存当前配置类所在包的一个bean
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
	//...
}
  • @Import(AutoConfigurationImportSelector.class)
    可以看到@EnableAutoConfiguration注解内使用了@Import注解完成导入功能,而AutoConfigurationImportSelector内部再解析@Import注解时会调用getAutoConfigurationEntry方法,
  1. getAutoConfigurationEntry方法进行扫描具有META-INF/spring.factories文件的jar包
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
		//...
		protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		//去重,点进源码发现就是将当前集合放置到LinkedHashSet中进行去重,然后再转换成List
		configurations = removeDuplicates(configurations);
		 //根据EnableAutoConfiguration注解中属性,获取不需要自动装配的类名单
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		// 根据:@EnableAutoConfiguration.exclude,excludeName和spring.autoconfigure.exclude进行删除
		checkExcludedClasses(configurations, exclusions);
		//exclusions也进行删除
		configurations.removeAll(exclusions);
	    /**
         *通过读取spring.factories所在jar中的
     	 *org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition进行删除
         */
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}
	//...
	/**
     * 从META-INF/spring.factories中获得候选的自动配置类
     */
		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部分源码
public final class SpringFactoriesLoader {

	/**
	 *工厂位置
	 */
	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
	//...
	}
  • 任何一个springboot应用,都会引入spring-boot-autoconfigure,而spring.factories文件就在该包下面。spring.factories文件是 Key=Value形式,多个Value时使用,隔开,该文件中定义了关于初始化,监听器等信息,而真正使自动配置生效的key是org.springframework.boot.autoconfigure.EnableAutoConfiguration
  • 最后:@EnableAutoConfiguration注解通过@SpringBootApplication间接的标注再SpringBoot的启动类上面,在执行SpringApplication.run(DemoApplication.class, args)时;找到所有JavaConfig自动配置类的全限定名对应的 class,然后将所有自动配置类加载到Spring容器中
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.番茄炒蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值