@SpringBootApplication
public class Demo2020Application {
public static void main(String[] args) {
SpringApplication.run(Demo2020Application.class, args);
}
}
首先我们看看@SpringBootApplication这个注解,点进去
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
// 自动扫描符合条件的Bean到容器中,这个注解会默认扫描声明类所在的包下面所有的包
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
再来看一下
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};
//指定多个包扫描
@AliasFor("value")
String[] basePackages() default {};
//对指定的类和接口所属的包扫描
Class<?>[] basePackageClasses() default {};
//未扫描到的bean自动命名
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
//指定代理是否被扫描
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
//是否开启对@Component@Repository@Service@Controller的类进行检测
boolean useDefaultFilters() default true;
//指定扫描的过滤器
Filter[] includeFilters() default {};
//指定不扫描的过滤器
Filter[] excludeFilters() default {};
// 是否对注册扫描的bean设置懒加载
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
}
下面我们看看@SpringBootConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
只是对@Configuration注解的一个封装
下面就是@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 {};
}
利用@Import
注解,将所有符合自动装配条件的bean注入到IOC容器中,进入AutoConfigurationImportSelector中
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//判断是不是禁用了自动配置
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 如果没有禁用
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected boolean isEnabled(AnnotationMetadata metadata) {
if (getClass() == AutoConfigurationImportSelector.class) {
return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
}
return true;
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//加载所有的预先定义的配置信息
//这些配置信息在org.springframework.boot.autoconfigure包下的META-INF/spring-autoconfigure-metadata.properties文件中
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);
}
上面还有一个文件spring.factories
这个文件基本上springboot的包都存在,而且所有的spring.factories都会加载
所以就可以在我们的项目的META-INF文件夹下建立一个spring.factories,写上我们自己的配置,然后项目启动的时候也会加载,这就是自义定starter