1.默认启动类:
@SpringBootApplication //注解
public class SpringbootDemo02Application {
public static void main(String[] args) {
//启动了一个服务
SpringApplication.run(SpringbootDemo02Application.class, args);
}
}
2.进入@SpringBootApplication;下面是主要的注解,序号是自己加的方便理解。
1. @SpringBootConfiguration
2. @EnableAutoConfiguration
3. @ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
// ......
}
2.1 @SpringBootConfiguration
作用:SpringBoot的配置类 ,标注在某个类上 ,表示这是一个SpringBoot的配置类;
看源码:点进@SpringBootConfiguration看到源码
1.//先点入@SpringBootConfiguration
@Configuration //表明是一个配置
@Indexed
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
2.//点进@Configuration ---->
@Component //是spring的一个组件
public @interface Configuration {
@AliasFor(
annotation = Component.class
)
String value() default "";
boolean proxyBeanMethods() default true;
}
(1)这里的 @Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件;
(2)里面的 @Component 这就说明,启动类本身也是Spring中的一个组件,负责启动应用!
2.2 @EnableAutoConfiguration
作用:开启自动配置功能
以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置 ;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效。
看源码:
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
//点击@AutoConfigurationPackage --->
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
@AutoConfigurationPackage:自动配置包
(1)点进:@AutoConfigurationPackage
@Import({Registrar.class}): 给spring容器导入一个组件;
Registrar.class : 将主启动类中的所有子包中的组件扫描到spring容器中;
(2)@Import({AutoConfigurationImportSelector.class}):
@Import({Registrar.class}): 给spring容器导入一个组件;
AutoConfigurationImportSelector.class :自动导入选择器
(3) AutoConfigurationImportSelector.class选择器中的一个类
(a)getCandidateConfigurations类
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}
(b)getCandidateConfigurations类调用了loadFactoryNames类
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
(c):loadFactoryNames类 去调用了 loadSpringFactories类;getResources("META-INF/spring.factories")得到了spring.factories
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryTypeName = ((String)entry.getKey()).trim();
String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
String[] var10 = factoryImplementationNames;
int var11 = factoryImplementationNames.length;
for(int var12 = 0; var12 < var11; ++var12) {
String factoryImplementationName = var10[var12];
((List)result.computeIfAbsent(factoryTypeName, (key) -> {
return new ArrayList();
})).add(factoryImplementationName.trim());
}
}
}
result.replaceAll((factoryType, implementations) -> {
return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
});
cache.put(classLoader, result);
return result;
} catch (IOException var14) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
}
}
}
(d):查找spring.factories文件
(f):我们根据源头打开spring.factories , 看到了很多自动配置的文件;这就是自动配置根源。
2.3 @ComponentScan:
这个注解在Spring中,它对应XML配置中的元素。
作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中
3.结论:
-
SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
-
将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
-
整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;
-
它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件 ;
-
有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;