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的使用》就可以了