我感觉三言两语说不明白,还是先根据源码,然后再图解的方式梳理一下。
@SpringBootApplication // 标注这个类是一个SpringBoot的应用
public class Logback02Application {
public static void main(String[] args) {
// 将SpringBoot应用启动
SpringApplication.run(Logback02Application.class, args);
}
}
梦开始的地方,下面要追的源码也就是
**@SpringBootApplication**
中的东西了
点进来以后就是这样子的,这里主要要了解的是
@SpringBootConfiguration
、@EnableAutoConfiguration
、@ComonentScan
点进去@SpringBootConfiguration
点进去@Configuration
@SpringBootConfiguration
:SpringBoot的配置类@Configuration
:spring的配置类@Component
:也是一个spring的组件点进@EnableAutoConfiguration
点进@AutoConfigurationPackage
@Import({AutoConfigurationPackages.Registrar.class})
:自动配置包注册
点进AutoConfigurationImportSelecto
这里面有好多好多的东西,下面就说几个重要的
点进getCandidateConfigurations,这个是getAutoConfigurationEntry里面的方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
这个是getCandidateConfigurations方法,获取候选的配置
进入getSpringFactoriesLoaderFactoryClass
进入EnableAutoConfiguration
最终发现这个找的就是主启动类
这个loadFactoryNames是getCandidateConfigurations的方法,获取所有的加载配置方法
这个也是getCandidateConfigurations中提到的,它是自动配置的核心文件,这里也写一下从哪里找到它
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
Map<String, List<String>> result = new HashMap();
try {
Enumeration<URL> 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()) {
Map.Entry<?, ?> entry = (Map.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);
}
}
}
这里就可以加载上面提到的META-INF/spring.factories的文件了
扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。如下图所示,容器中将排除TypeExcludeFilter和AutoConfigurationExcludeFilter