SpringBoot源码解析(一)------启动@SpringBootApplication注解

主程序类(主入口类)

@SpringBootApplication
public class HelloWorldMainApplication {

    public static void main(String[] args) {
        //Spring应用启动
        SpringApplication.run(HelloWorldMainApplication.class, args);
    }
}

@SpringBootApplication注解定义如下:

@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. @SpringBootConfiguration注解

  • SpringBoot的配置类
  • 标注在某个类上,表示这是一个Spring Boot的配置类

定义如下:

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

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

}

其实就是一个Configuration配置类,就是这个主类最终会被注册到Spring容器中

2.@EnableAutoConfiguration注解

  • 开启自动配置功能
  • 之前Spring需要配置的信息,SpringBoot帮助自动配置
  • @EnableAutoConfiguration通知SpringBoot开启自动配置功能,这样自动配置才能生效

注解定义如下:

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

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

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

	String[] excludeName() default {};

}

3.@AutoConfigurationPackage自动配置包注解

注解定义如下:

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

	String[] basePackages() default {};

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

其中@Import(AutoConfigurationPackages.Register.class)默认将主配置类所在包及其子包里面的所有组件扫描到容器中,如下:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
       //默认将会扫描@SpringBootApplication标注的主配置类所在的包及其子包下所有组件
	   register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
	}
        @Override
	public Set<Object> determineImports(AnnotationMetadata metadata) {
	   return Collections.singleton(new PackageImports(metadata));
	}
}

4.@Import(EnableAutoConfigurationImportSelector.class)

EnableAutoConfigurationImportSelector:导入哪些组建的选择器,将所有需要导入的组件以全类名的方式返回,这些组建将会被添加到容器中。主要是在父类AutoConfigurationImportSelector中实现的,如下:

public String[] selectImports(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return NO_IMPORTS;
	}
	AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
	return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

其中主要是getAutoConfigurationEntry方法,如下:

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return EMPTY_ENTRY;
	}
	AnnotationAttributes attributes = getAttributes(annotationMetadata);
        // 会给容器注入众多自动配置类(XXXAutoConfiguration)
	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;
}


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

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

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
	MultiValueMap<String, String> result = cache.get(classLoader);
	if (result != null) {
		return result;
	}
	try {
          // 从类路径的META-INF/spring.factories中加载所有默认的自动配置类
	   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()) {
           //获取EnableAutoConfiguration指定的所有值,也就是EnableAutoConfiguration.class的值
		    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);
	}
}

SpringBoot启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,并将这些值作为自动配置类导入到容器中,自动配置类就会生效,最后完成自动配置工作。EnableAutoConfiguration默认在sping-boot-autoconfiguration这个包中,如图:

最终有96个自动配置类被加载并注册进Spring容器中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值