自动化装配源码
- @EnableAutoConfiguration 注解,开启自动配置的核心注解
- @AutoConfigurationPackage 注解
- AutoConfigurationImportSelector 类
- getAutoConfigurationEntry 方法
- getCandidateConfigurations 方法
- SpringFactoriesLoader
@EnableAutoConfiguration 注解,开启自动配置的核心注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {...
}
@EnableAutoConfiguration 包含了@AutoConfigurationPackage 注解和 @Import(AutoConfigurationImportSelector.class) 注解。
@AutoConfigurationPackage 注解
@AutoConfigurationPackage 通过 AutoConfigurationPackages.Registrar 将应用主类所在包及其子包下的所有组件扫描到Spring容器中。
重写这个方法就可以把包注册到spring 容器里面
有4个接口和一个注解都可以把对应类型放到容器里面,上文从源码来看是约定了一个接口,具体如何注册,看实现方式 AutoConfigurationPackages.register(registry, (new PackageImport(metadata)).getPackageName());
放到了定义map中
放到bean工厂,容器启动加载进去指的一说的是这个类,核心类 DefaultListableBeanFactory
从图中可以看到实现了 BeanFactory 接口和 ListableBeanFactory、ConfigurableListableBeanFactory、AutowireCapableBeanFactory 等多个接口。这个类是 Spring 容器的默认实现之一,是一个全功能的 Spring Bean 工厂,提供对 Bean 的完整管理,包括 Bean 的创建、定义、解析依赖、配置等功能
AutoConfigurationImportSelector 类
AutoConfigurationImportSelector 主要作用是收集和加载所有的自动配置类。
public class AutoConfigurationImportSelector extends ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}
}
getAutoConfigurationEntry 方法
getAutoConfigurationEntry 方法用于获取所有的自动配置类:
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {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);configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
}
getCandidateConfigurations 方法
getCandidateConfigurations 方法从 spring.factories 文件中加载所有的候选配置类:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), 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;
}
SpringFactoriesLoader
SpringFactoriesLoader.loadFactoryNames 方法会读取 META-INF/spring.factories 文件中的配置,获取所有自动配置类的全限定名。
public abstract class SpringFactoriesLoader {private static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap<>();public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {String factoryClassName = factoryClass.getName();return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());}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");// 下面先别管MultiValueMap<String, String> 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()) {Map.Entry<?, ?> entry = (Map.Entry)var6.next();String factoryClassName = ((String)entry.getKey()).trim();String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());int var10 = var9.length;for(int var11 = 0; var11 < var10; ++var11) {String factoryName = var9[var11];result.add(factoryClassName, factoryName.trim());}}}cache.put(classLoader, result);return result;} catch (IOException var13) {throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);}}}}
基本就结束了