@EnableAutoConfiguration
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
- @AutoConfigurationPackage
- @Import(AutoConfigurationImportSelector.class)
- public @interface EnableAutoConfiguration {
- String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
- Class<?>[] exclude() default {};
- String[] excludeName() default {};
- }
标注了@AutoConfigurationPackage,并且导入了AutoConfigurationImportSelector
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Inherited
- @Import(AutoConfigurationPackages.Registrar.class)
- public @interface AutoConfigurationPackage {
- }
@AutoConfigurationPackage注解导入了AutoConfigurationPackages.Registrar。
下面来看看这两个导入类
AutoConfigurationPackages.Registrar
这是一个内部类,外部类AutoConfigurationPackages是一个抽象类
- 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));
- }
- }
注册
- private final String packageName;
- PackageImport(AnnotationMetadata metadata) {
- this.packageName = ClassUtils.getPackageName(metadata.getClassName());
- }
PackageImport也是一个内部类,构造方法中赋值了一个成员变量packageName。
- public static String getPackageName(String fqClassName) {
- Assert.notNull(fqClassName, "Class name must not be null");
- int lastDotIndex = fqClassName.lastIndexOf(PACKAGE_SEPARATOR);
- return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : "");
- }
getPackageName方法中会根据@AutoConfigurationPackage标注类的全限定名,获取@AutoConfigurationPackage标注类的包名。
然后将@AutoConfigurationPackage标注类的包名赋值给PackageImport的成员变量packageName。
- String getPackageName() {
- return this.packageName;
- }
getPackageName方法只是简单的将PackageImport#packageName返回。
然后调用外部类AutoConfigurationPackages的静态方法register
- private static final String BEAN = AutoConfigurationPackages.class.getName();
- public static void register(BeanDefinitionRegistry registry, String... packageNames) {
- //已经注册过 BEAN 了,代表不是第一次调用AutoConfigurationPackages.Registrar
- if (registry.containsBeanDefinition(BEAN)) {
- BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
- ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
- //将这次调用AutoConfigurationPackages.Registrar,将标注@AutoConfigurationPackage 注解的类的包名添加到 BEAN 的参数中
- constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));
- }
- else {
- //第一次调用AutoConfigurationPackages.Registrar,注册 BEAN
- GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
- beanDefinition.setBeanClass(BasePackages.class);
- //获取BasePackages构造器的参数,是个 String... ,将packageNames放到数组第一个位置
- beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
- beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
- registry.registerBeanDefinition(BEAN, beanDefinition);
- }
- }
注册AutoConfigurationPackages
- static final class BasePackages {
- private final List<String> packages;
- private boolean loggedBasePackageInfo;
- BasePackages(String... names) {
- List<String> packages = new ArrayList<>();
- for (String name : names) {
- if (StringUtils.hasText(name)) {
- packages.add(name);
- }
- }
- this.packages = packages;
- }
- List<String> get() {
- if (!this.loggedBasePackageInfo) {
- if (this.packages.isEmpty()) {
- if (logger.isWarnEnabled()) {
- ...//只是输出日志
- }
- }
- else {
- if (logger.isDebugEnabled()) {
- String packageNames = StringUtils.collectionToCommaDelimitedString(this.packages);
- ...//输出日志
- }
- }
- this.loggedBasePackageInfo = true;
- }
- return this.packages;
- }
- }
注册时bean的名称是上面的 BEAN,bean的类为BasePackages。
已经注册过AutoConfigurationPackages
- private static String[] addBasePackages(ConstructorArgumentValues constructorArguments, String[] packageNames) {
- //取出BasePackages构造器的参数 String...
- String[] existing = (String[]) constructorArguments.getIndexedArgumentValue(0, String[].class).getValue();
- //创建新的集合,将原有的包名和现有的包名添加进去,用set去重,然后返回
- Set<String> merged = new LinkedHashSet<>();
- merged.addAll(Arrays.asList(existing));
- merged.addAll(Arrays.asList(packageNames));
- return StringUtils.toStringArray(merged);
- }
AutoConfigurationImportSelector
AutoConfigurationImportSelector实现了DeferredImportSelector,DeferredImportSelector实现了ImportSelector。
- public String[] selectImports(AnnotationMetadata annotationMetadata) {
- //不起用自动装配
- if (!isEnabled(annotationMetadata)) {
- return NO_IMPORTS;
- }
- //获得AutoConfiguration的注解元数据
- AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
- .loadMetadata(this.beanClassLoader);
- AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
- annotationMetadata);
- return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
- }
- protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
- AnnotationMetadata annotationMetadata) {
- if (!isEnabled(annotationMetadata)) {
- return EMPTY_ENTRY;
- }
- //获取注解的属性
- AnnotationAttributes attributes = getAttributes(annotationMetadata);
- //获取实现EnableAutoConfiguration的类名集合
- 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);
- }
获取所有EnableAutoConfiguration实现类名
- protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
- //利用spi获取实现了EnableAutoConfiguration的类名集合
- 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;
- }
- protected Class<?> getSpringFactoriesLoaderFactoryClass() {
- return EnableAutoConfiguration.class;
- }
去重
- protected final <T> List<T> removeDuplicates(List<T> list) {
- return new ArrayList<>(new LinkedHashSet<>(list));
- }
获取要排除的类名
- protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
- Set<String> excluded = new LinkedHashSet<>();
- excluded.addAll(asList(attributes, "exclude"));
- excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
- excluded.addAll(getExcludeAutoConfigurationsProperty());
- return excluded;
- }
- private List<String> getExcludeAutoConfigurationsProperty() {
- if (getEnvironment() instanceof ConfigurableEnvironment) {
- Binder binder = Binder.get(getEnvironment());
- return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList)
- .orElse(Collections.emptyList());
- }
- String[] excludes = getEnvironment().getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
- return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
- }
过滤
- private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
- long startTime = System.nanoTime();
- String[] candidates = StringUtils.toStringArray(configurations);
- boolean[] skip = new boolean[candidates.length];
- boolean skipped = false;
- for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
- invokeAwareMethods(filter);
- boolean[] match = filter.match(candidates, autoConfigurationMetadata);
- for (int i = 0; i < match.length; i++) {
- if (!match[i]) {
- skip[i] = true;
- candidates[i] = null;
- skipped = true;
- }
- }
- }
- if (!skipped) {
- return configurations;
- }
- List<String> result = new ArrayList<>(candidates.length);
- for (int i = 0; i < candidates.length; i++) {
- if (!skip[i]) {
- result.add(candidates[i]);
- }
- }
- if (logger.isTraceEnabled()) {
- int numberFiltered = configurations.size() - result.size();
- logger.trace("Filtered " + numberFiltered + " auto configuration class in "
- + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
- }
- return new ArrayList<>(result);
- }
- protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
- return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
- }
根据AutoConfigurationImportFilter的实现类过滤自动装配类
到此这篇关于SpringBoot快速通关自动配置应用的文章就介绍到这了,更多相关SpringBoot自动配置内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!