1.创建一个springboot项目
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导入类或者组件,导入类,分三种
- 直接导入普通的类
- 导入实现了ImportSelector接口的类
- 导入实现了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的使用》就可以了