@SpringBootApplication
首要先分析这个入口注解
这是@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) })
@SpringBootConfiguration
这是@SpringBootConfiguration下的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration//实际意义上有用的注解
表示注解相当于是@Configuration
@ComponentScan
用于扫描Component的配置注解和自动装配实现不太相关
分析一下@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
以上注解忽略
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage
分析该注解里的@Import(AutoConfigurationPackages.Registrar.class)
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}
}
该类实现了ImportBeanDefinitionRegistrar和spring的后置处理器处理相关,但是我们可以知道当spring启动时会调用registerBeanDefinitions去注册bean到ioc容器中
new PackageImport(metadata).getPackageName()
把当前这个注解的路径放入这个内部类的属性中
PackageImport(AnnotationMetadata metadata) {
this.packageName = ClassUtils.getPackageName(metadata.getClassName());
}
回到上层register()方法
//org.springframework.boot.autoconfigure.AutoConfigurationPackages
private static final String
BEAN = AutoConfigurationPackages.class.getName();
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
//当前registry就相当于spring的一个上下文此处判断了一下这个BEAN 的信息存不存在spring中由于是jar方式启动当前肯定不在所以走else逻辑
if (registry.containsBeanDefinition(BEAN)) {
BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));
}
else {
//代码一定运行到此处
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(BasePackages.class);
//这里把之前new PackageImport(metadata)的放入的属性传入进来了
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 把这个bean注册到spring中去
registry.registerBeanDefinition(BEAN, beanDefinition);
}
}
所以说这个类和自动装配也不太相关往下继续走
自动装配核心@Import(AutoConfigurationImportSelector.class)
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered
该类实现了 DeferredImportSelector当这个类@Import导入进spring容器中
当执行到后置处理器时会调用该类的selectImports方法
重点分析此方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//判断有没有开启自动装配
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//将这个类的加载器的元信息拿出来
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//核心
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
//仅仅转换list
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
分析getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
//EnableAutoConfiguration判断有没有
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//获取注解信息
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取自动装配对象
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//去重
configurations = removeDuplicates(configurations);
//获取需要排除的类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//检查排除类的正确性
checkExcludedClasses(configurations, exclusions);
//删除排除的自动装配类
configurations.removeAll(exclusions);
//将一些放在ioc容器并过滤扫描出来的类主要是过滤条件注解
//@ConditionalOnWebApplication
//@ConditionalOnClass
//@ConditionalOnBean等等
configurations = filter(configurations, autoConfigurationMetadata);
//装配监听器
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
获取注解信息AnnotationAttributes attributes = getAttributes(annotationMetadata);
getCandidateConfigurations()->loadFactoryNames()->loadSpringFactories()
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
//启动从此处获取缓存肯定是null
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
//从"META-INF/spring.factories";读取url
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
//将文件load成properties
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
//遍历文件
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
//存储kv键值对
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
//缓存
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
以下两个方法和上述逻辑类似直接过
filter(configurations, autoConfigurationMetadata);
spring.factroies下
Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=
org.springframework.boot.autoconfigure.condition.OnBeanCondition,
org.springframework.boot.autoconfigure.condition.OnClassCondition,
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
fireAutoConfigurationImportEvents(configurations, exclusions);
spring.factroies下
Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener