Spring Boot自动配置原理

一、Spring Boot自动配置

在初学spring,使用SSM框架时,我们做了大量的配置工作,数据源、连接池、会话工厂、映射器、视图解析器等各种配置,而现在在Spring Boot中这些工作都不需要了,全部都交给了自动配置来做。简单来说Spring Boot自动配置就是用注解来对一些常规的配置做默认配置,简化xml配置内容,使项目能够快速运行。
下面我们就来看下Spring Boot自动配置的原理。

二、Spring Boot自动配置

在启动类中可以看到@SpringBootApplication注解,它是SpringBoot的核心注解,也是一个组合注解。我们进入这个注解可以看到里面又包含了其它很多注解,其中@SpringBootConfiguration、@EnableAutoConfiguration、@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}
)}
)

而实现自动配置的就是其中的@EnableAutoConfiguration注解,进入@EnableAutoConfiguration,可以看到这两个注解:@AutoConfigurationPackage和@Import,这里我们需要关心的是这个@Import注解

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

1.@AutoConfigurationPackage

AutoConfigurationPackage注解的作用是将 添加该注解的类所在的package 作为 自动配置package 进行管理。可以通过 AutoConfigurationPackages 工具类获取自动配置package列表。当通过注解@SpringBootApplication标注启动类时,已经为启动类添加了@AutoConfigurationPackage注解。路径为 @SpringBootApplication -> @EnableAutoConfiguration -> @AutoConfigurationPackage。也就是说当SpringBoot应用启动时默认会将启动类所在的package作为自动配置的package。

2.@Import

@Import这个注解中导入了AutoConfigurationImportSelector类。这个类中有一个非常重要的方法——selectImports(),它几乎涵盖了组件自动装配的所有处理逻辑,包括获得候选配置类、配置类去重、排除不需要的配置类、过滤等,最终返回符合条件的自动配置类的全限定名数组。

	@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);
		//获得注解中被exclude和excludeName排除的类的集合
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		//检查被排除类是否可实例化、是否被自动注册配置所使用,不符合条件则抛出异常
		checkExcludedClasses(configurations, exclusions);
		//从候选配置类中去除掉被排除的类
		configurations.removeAll(exclusions);
		//过滤
		configurations = filter(configurations, autoConfigurationMetadata);
		//将配置类和排除类通过事件传入到监听器中
		fireAutoConfigurationImportEvents(configurations, exclusions);
		//最终返回符合条件的自动配置类的全限定名数组
		return StringUtils.toStringArray(configurations);
	}

可以看到所有的配置信息通过getCandidateConfigurations()得到,并最终由一个列表保存。继续查看getCandidateConfigurations()方法。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
    }

再进入loadFactoryNames()中可以看到包名叫做autoConfiguration的包下面有名为META-INF/spring.factories的文件

Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                LinkedMultiValueMap result = new LinkedMultiValueMap();

简单点说以上过程就是:getCandidateConfigurations()方法通过SpringFactoriesLoader加载器加载META-INF/spring.factories文件——>通过这个文件获取到每个配置类的url——>通过这些url将它们封装成Properties对象——>解析内容存于Map<String,List>中——>通过loadFactoryNames传递过来的class名称作为Key从Map中获得该类的配置列表——>getCandidateConfigurations()方法获取到了配置类并存于List中——>通过selectImports()方法返回一个自动配置类的全限定名数组。

最后得到的自动配置类的全限定名数组,这些配置类需要在满足@Condition后才能真正的被注册到Spring容器之中。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值