浅析Spring Boot中的自动配置原理

本文深入剖析SpringBoot的自动配置原理,从@SpringBootApplication入手,详细解读@EnableAutoConfiguration、@ComponentScan和@SpringBootConfiguration的作用及其实现机制,并以MyBatis为例说明starter依赖自动配置的过程。


目录

前言

一、SpringBoot的自动配置原理

@SpringBootApplication

@SpringBootApplication其中的三个重要注解

二、SpringBoot自动配置相关

总结


前言

初次搭SpringBoot环境的时候,一看到项目搭起来就不得不惊叹前辈大牛的牛x之处。习惯了SSM的繁琐操作之后,使用SpringBoot无需各种POM坐标,只要just run就能跑起来。

SpringBoot的核心就是自动配置,所以今天刚好有空就来看看SpringBoot到底是如何实现自动配置的。

一、SpringBoot的自动配置原理

Springboot的自动配置是通过 SpringBootApplication 注解实现的。

@SpringBootApplication

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

点进去可以看到它其中我们比较看重的功能实际上由三个注解组成。

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

@SpringBootApplication其中的三个重要注解

  1. @EnableAutoConfiguration
  2. @ComponentScan
  3. @SpringBootConfiguration

@EnableAutoConfiguration是开启自动配置功能的,下面再详细讲。

@ComponentScan 注解,则是用于扫描被 Component 注解的类(以当前类(Application类启动类)所在的包为基包递归扫描),这个在之前SSM项目中就已经见过很多遍了

@SpringBootConfiguration,根据Spring文档,@SpringBootConfiguration是Spring标准@Configuration批注的替代方法。区别在于@SpringBootConfiguration允许自动找到配置。

重点来看看@EnableAutoConfiguration

@EnableAutoConfiguration是springboot实现自动化配置的核心注解

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

可以看到

@EnableAutoConfiguration通过@Import注入了一个ImportSelector的实现类,筛选了哪些是需要自动配置的。

继续点进去看

	/**
	 * Return the auto-configuration class names that should be considered. By default
	 * this method will load candidates using {@link SpringFactoriesLoader} with
	 * {@link #getSpringFactoriesLoaderFactoryClass()}.
	 * @param metadata the source metadata
	 * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
	 * attributes}
	 * @return a list of candidate configurations
	 */
	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;
	}

其中有一个getCandidateConfigurations方法,很明显springboot是通过它加载了spring factories

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

通过这一行

List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

spring boot扫描了META-INF/spring.factories文件
 

————————————————
 

二、SpringBoot自动配置相关

 再看看mybatis是怎么通过starter依赖自动配置的

spring.factories文件中记录着自动配置类AutoConfigurationClass

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

继续往下我们看到了 

@EnableConfigurationProperties(MybatisProperties.class)
public class MybatisAutoConfiguration implements InitializingBean {
    private final MybatisProperties properties;

这个MybatisProperties怎么看都和新建项目就有的application.properties很像吧,继续点进去看

@ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
public class MybatisProperties {

  public static final String MYBATIS_PREFIX = "mybatis";

  private static final ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();

  /**
   * Location of MyBatis xml config file.
   */
  private String configLocation;

  /**
   * Locations of MyBatis mapper files.
   */
  private String[] mapperLocations;

  /**
   * Packages to search type aliases. (Package delimiters are ",; \t\n")
   */
  private String typeAliasesPackage;

原来这些configLocation,typeAliasesPackage等等就是我们在application.properties中给mybatis中配置的属性。


总结

Spring boot真好用

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值