0
点赞
收藏
分享

微信扫一扫

SpringBoot学习笔记(三)自动装配


一.SpringBoot的自动装配

1.@Import(AutoConfigurationImportSelector.class)

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered

2.DeferredImprotSelector

public interface DeferredImportSelector extends ImportSelector

  • DeferredImprotSelector是ImprotSelector的一种扩展
  • 在处理完所有的 @Configuration类型的Bean之后运行
  • 当导入@Conditional时,这种类型选择器特别有用
  • 实现还可以扩展Ordered接口,或使用@Order注解指示对其DeferredImportSelector优先级

总结:

  • 执行时机:在@configuration注解中其他逻辑被处理完毕之后(包括对@ImprotResource,@Bean)再执行
  • DeferredImportSelector执行时机ImprotSelector更晚

中其

二.AutoConfigurationImportSelector的核心

@override
public String[] selectImports(AnnotationMetadata annotationMetadata){
if(!isEmabled(annotationMetadata)){
return NO_IMPORTS;

}
AutoconfigurationMetadata autoConfigurationMetadata=AutoconfigurationMetadataLoder.loadMetadata(this.beanClassLoader);
// 加载自动配置类
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);

return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

三.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata)

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata){
if(!isEnabled(annotationMetadata)){
return EMPTY_ENTRY;
}
AnnotationAttributes attributes=getAttributes(annotationMetadata);
//核心-加载候选的自动配置类
List<String> configurations=getCandidateConfigurations(annotationMetadata, attribute);
configurations=removeDuplicates(configurations);
Set<String> exclusions=getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}

四.SpringBoot使用的工厂机制

 1.java的SPI

  • SPI全称Service Provider Interface
  • jdk内置服务提供发现机制---动态替换发现的机制

 2.SpringFramework的SpringFactoriesLoader

 loadFactoryNames方法:

public static List<String> loadFactoryNames(Class<?> factoryClass,@Nullable ClassLoader classLoader){
String factoryClassName = factoryClass.getName();
return laodSpringFactories(classLoader).getOrDefault(factoryClassName,Collections.emptyList());

}

3.loadSpringFactories的实现,其中有缓存的写法值得学习

public static final String FACTORIES_RESOURCE_LOCATION="META-INF/spring.factories";

private static final Map<ClassLoader,MultiValueMap<String, String>> cache=new ConcurrentReferenceHashMap<>();

private static Map<String,List<String>> loadSpringFactories(@Nullable ClassLoader classLoader){

Map<ClassLoader,MultiValueMap<String, String>> result=cache.get(classLoader);
if(result!=null){
return result;
}
try{
//获取当前 classpath 下所有jar包中有的 spring.factories 文件,并将它们加载到内存中
Enumeration<URL> urls=(classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
//每一个文件,并用 Properties 方式加载文件,之后把这个文件中每一组键值对都加载出来,放入 MultiValueMap 中
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryClassName = ((String) entry.getKey()).trim();
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;

}catch (IOException ex){
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION +"]",ex );
}

}

五.总结

  • AutoconfigurationImprotSelector 配合SpringFactoriseLoader可加载“META-INF/spring.factories”中配置@EnableAutoconfiguration对应的自动配置类
  • deferredImportSelector的执行时机比ImprotSelector更晚
  • SpringFramework 实现了自己的SPI技术,相比较于Java原生的SPI更灵活。
举报

相关推荐

0 条评论