文章目录
一、spring版本发展
二、SpringBoot版本发展
三、SpringBoot自动装配原理分析
Spring容器初始化
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(KafkaApplication.class);
spring boot启动类
@SpringBootApplication
public class KafkaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(KafkaApplication.class,args);
}
}
如上图可知,spring boot应用程序启动的过程初始化了spring容器
1、run方法源码
public ConfigurableApplicationContext run(String... args) {
//StopWatch用于程序启动时间的统计
StopWatch stopWatch = new StopWatch();
//时间的统计开始
stopWatch.start();
//定义方法返回的对象
ConfigurableApplicationContext context = null;
//获取环境属性信息
this.configureHeadlessProperty();
//发布事件的监听器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
try {
//应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//环境信息
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
//创建应用上下文对象(判断了环境类型)
context = this.createApplicationContext();
//刷新前的处理
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新上下文(spring容器)
this.refreshContext(context);
//刷新后的处理
this.afterRefresh(context, applicationArguments);
//时间的统计结束
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var9) {
this.handleRunFailure(context, var9, listeners);
throw new IllegalStateException(var9);
}
try {
listeners.running(context);
return context;
} catch (Throwable var8) {
this.handleRunFailure(context, var8, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var8);
}
}
2、启动类注解分析
1、@EnableAutoConfiguration
AutoConfigurationImportSelector.calss
AutoConfigurationImportSelector.class
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//获取所有的候选的配置信息(读取所有META-INF/spring.factories文件所得类的全路径名)
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
//移除重复的配置类
configurations = this.removeDuplicates(configurations);
//移除 显示排除自动加载的类(例如@SpringBootApplication(exclude = DataSourceAutoConfiguration.class))
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//过滤掉不需要载入的配置类(移除未引入starter的配置类)
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
1 分析://获取所有的候选的配置信息(读取所有META-INF/spring.factories文件所得类的全路径名)
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
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;
}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
读取 META-INF/spring.factories 获取配置类信息
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
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[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryImplementationName = var9[var11];
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
2 分析: //过滤掉不需要载入的配置类(移除未引入starter的配置类)
configurations = this.getConfigurationClassFilter().filter(configurations);
List<String> filter(List<String> configurations) {
long startTime = System.nanoTime();
String[] candidates = StringUtils.toStringArray(configurations);
boolean skipped = false;
Iterator var6 = this.filters.iterator();
int i;
while(var6.hasNext()) {
AutoConfigurationImportFilter filter = (AutoConfigurationImportFilter)var6.next();
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
for(i = 0; i < match.length; ++i) {
if (!match[i]) {
candidates[i] = null;
skipped = true;
}
}
}
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
private final AutoConfigurationMetadata autoConfigurationMetadata;
private final List<AutoConfigurationImportFilter> filters;
ConfigurationClassFilter(ClassLoader classLoader, List<AutoConfigurationImportFilter> filters) {
this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(classLoader);
this.filters = filters;
}
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
return loadMetadata(classLoader, "META-INF/spring-autoconfigure-metadata.properties");
}
3、自定义第三方starter(不是springboot项目不需要写启动类)
1)创建maven项目
2)编辑自定义的项目核心代码完成业务逻辑
示例配置类:
package com.buba.config;
@Configuration
public class FeignConfig {
@Bean
public Request.Options options(){
return new Request.Options(5000,5000);
}
@Bean
public User user(){
return new User();
}
}
3)创建资源文件
按spring-boot-autoconfigure的文件格式编辑,定义自己的配置类加载条件
resource/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.buba.config.FeignConfig
resource/META-INF/spring.factories
com.buba.config.FeignConfig.ConditionalOnClass=XX.XX.XX
4) 使用springboot工程,添加自己定义的项目依赖
启动springboot工程即可将自定义的工程中交给容器管理的对象进行初始化并添加到容器