springboot2.0 主程序类@SpringBootApplication详解,@SpringBootConfiguration,@EnableAutoConfiguration

1.创建一个springboot项目

《 spring boot2.0 第一个程序《快速开始》》

2.项目主类入口

package com.badger.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootHelloApplication {

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

我们首先springboot的第一个注解@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 {};

	//自动注入的时候,扫描的类注解(@Service,@Controller等)
	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};

}

我们可以看到,@SpringBootApplication注解,是三个组合注解:@SpringBootConfiguration  @EnableAutoConfiguration @ComponentScan

1)@SpringBootConfiguration:标注这个类是一个配置类

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

}

可以看到,这个注解,只是@Configuration注解的派生注解,跟@Configuration注解的功能一致,标注这个类是一个配置类,只不过@SpringBootConfiguration是springboot的注解,而@Configuration是spring的注解,关于@Configuration注解,更详细的,可以参看《spring注解 @Conditional的使用》

《springboot2.0 @Conditional派生注解@ConditionalOnMissingBean,@ConditionalOnProperty等详解》

2).@EnableAutoConfiguration注解:开启自动装配

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

}

@EnableAutoConfiguration注解,又是一个组合注解:@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)

@Import(AutoConfigurationImportSelector.class) 导入AutoConfigurationImportSelector.class类

关于@Import注解,可以像@Configuration导入类或者组件,导入类,分三种

  1. 直接导入普通的类
  2. 导入实现了ImportSelector接口的类
  3. 导入实现了ImportBeanDefinitionRegistrar接口的类

可以详细参考《spring注解 @Import的使用,ImportSelector接口,ImportBeanDefinitionRegistrar接口》

AutoConfigurationImportSelector.class的作用

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
				autoConfigurationMetadata, annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

 直接看重写的public String[] selectImports(AnnotationMetadata annotationMetadata)方法,查看getAutoConfigurationEntry法

AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
				autoConfigurationMetadata, annotationMetadata);

 

查看getCandidateConfigurations方法,根据条件配置

 可以看到,加载文件到list中,查看SpringFactoriesLoader.loadFactoryNames的方法

最终,会拿到所有的类的全路径,然后反射实例化bean,并注入到spring容器中,静态变量就是获取文件的路径

META-INF/spring.factories

/**
	 * The location to look for factories.
	 * <p>Can be present in multiple JAR files.
	 */
	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

 

这个部分,也是springboot自动装配的整个过程 

@AutoConfigurationPackage注解:自动配置包

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

}

@AutoConfigurationPackage注解,自动注入主类下所在包下(com.badger.web.SpringbootHelloApplication),所有的加了注解的类(@Controller,@Service等),以及配置类(@Configuration)

可以看到,就是@Import(AutoConfigurationPackages.Registrar.class)注解,导入(实例化)一个AutoConfigurationPackages.Registrar.class类;

我们直接看这个AutoConfigurationPackages.Registrar.class类的一些简单实现

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata,
				BeanDefinitionRegistry registry) {
            //new PackageImport(metadata).getPackageName() 扫描主类包下的所有的类 ,
            //并且注入到spring容器
			register(registry, new PackageImport(metadata).getPackageName());
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImport(metadata));
		}

	}

,感兴趣的,可以继续看下 

register(registry, new PackageImport(metadata).getPackageName());

3) @ComponentScan注解:包扫描

大家详细参看《spring注解 @ComponentScan,@ComponentScans 以及@Filter的使用》就可以了 

原创文章 83 获赞 155 访问量 36万+

猜你喜欢

转载自blog.csdn.net/qq_28410283/article/details/91353603