SpringBoot源码解析(三):@SpringBootApplication组合注解的底层实现

前言

@SpringBootApplication注解是SpringBoot应用的核心入口注解,它实际上是一个组合注解(Composite Annotation),集成了SpringBoot自动配置的核心功能。本文将深入剖析@SpringBootApplication注解的底层实现原理,从元注解解析、自动配置机制到组件扫描流程,全面解析SpringBoot启动的核心魔法。通过本文,读者将透彻理解SpringBoot自动配置的工作机制及其底层实现细节。

一、@SpringBootApplication注解概览

1.1 注解定义

@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)
})
public @interface SpringBootApplication {
    
    @AliasFor(annotation = EnableAutoConfiguration.class)
    Class[] exclude() default {};
    
    @AliasFor(annotation = EnableAutoConfiguration.class)
    String[] excludeName() default {};
    
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};
    
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class[] scanBasePackageClasses() default {};
    
    @AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
    Class nameGenerator() default BeanNameGenerator.class;
    
    @AliasFor(annotation = Configuration.class)
    boolean proxyBeanMethods() default true;
}

1.2 核心元注解

  1. @SpringBootConfiguration:标识为SpringBoot配置类
  2. @EnableAutoConfiguration:启用自动配置机制
  3. @ComponentScan:启用组件扫描

二、@SpringBootConfiguration解析

2.1 注解定义

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
    
    @AliasFor(annotation = Configuration.class)
    boolean proxyBeanMethods() default true;
}

2.2 与@Configuration的关系

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    
    @AliasFor(annotation = Component.class)
    String value() default "";
    
    boolean proxyBeanMethods() default true;
}

@SpringBootConfiguration本质上是一个特化的@Configuration,用于标识SpringBoot的主配置类。它通过@Indexed注解支持编译时索引,加速组件扫描。

三、@EnableAutoConfiguration深度解析

3.1 注解定义

@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 {};
}

3.2 @AutoConfigurationPackage解析

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
    
    String[] basePackages() default {};
    
    Class[] basePackageClasses() default {};
}

AutoConfigurationPackages.Registrar负责注册自动配置的基础包:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata,
            BeanDefinitionRegistry registry) {
        register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
    }
    
    @Override
    public Set determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new PackageImports(metadata));
    }
} 
  

3.3 AutoConfigurationImportSelector核心实现

AutoConfigurationImportSelector是实现自动配置的核心类:

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
        ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
    
    protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List configurations = getCandidateConfigurations(annotationMetadata, attributes);
        configurations = removeDuplicates(configurations);
        Set exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = getConfigurationClassFilter().filter(configurations);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }
    
    protected List getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List configurations = SpringFactoriesLoader.loadFactoryNames(
                EnableAutoConfiguration.class, getBeanClassLoader());
        Assert.notEmpty(configurations,
                "No auto configuration classes found in META-INF/spring.factories");
        return configurations;
    }
}

3.4 自动配置过滤机制

SpringBoot 2.4.0引入了新的过滤机制:

private ConfigurationClassFilter getConfigurationClassFilter() {
    if (this.configurationClassFilter == null) {
        List filters = getAutoConfigurationImportFilters();
        for (AutoConfigurationImportFilter filter : filters) {
            invokeAwareMethods(filter);
        }
        this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);
    }
    return this.configurationClassFilter;
}

protected List getAutoConfigurationImportFilters() {
    return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}

四、@ComponentScan定制解析

4.1 排除过滤器实现

@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
4.1.1 TypeExcludeFilter
public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware {
    
    private BeanFactory beanFactory;
    
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
    
    @Override
    public boolean match(MetadataReader metadataReader,
            MetadataReaderFactory metadataReaderFactory) throws IOException {
        if (this.beanFactory instanceof ListableBeanFactory && getClass() == TypeExcludeFilter.class) {
            Collection delegates = ((ListableBeanFactory) this.beanFactory)
                    .getBeansOfType(TypeExcludeFilter.class).values();
            for (TypeExcludeFilter delegate : delegates) {
                if (delegate.match(metadataReader, metadataReaderFactory)) {
                    return true;
                }
            }
        }
        return false;
    }
}
4.1.2 AutoConfigurationExcludeFilter
public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware {
    
    private ClassLoader beanClassLoader;
    
    @Override
    public void setBeanClassLoader(ClassLoader beanClassLoader) {
        this.beanClassLoader = beanClassLoader;
    }
    
    @Override
    public boolean match(MetadataReader metadataReader,
            MetadataReaderFactory metadataReaderFactory) throws IOException {
        return isAutoConfiguration(metadataReader) &&
                !isConfiguration(metadataReader) &&
                !isComponent(metadataReader);
    }
    
    private boolean isAutoConfiguration(MetadataReader metadataReader) {
        return metadataReader.getAnnotationMetadata()
                .isAnnotated(AutoConfiguration.class.getName());
    }
    
    private boolean isConfiguration(MetadataReader metadataReader) {
        return metadataReader.getAnnotationMetadata()
                .isAnnotated(Configuration.class.getName());
    }
    
    private boolean isComponent(MetadataReader metadataReader) {
        return metadataReader.getAnnotationMetadata()
                .isAnnotated(Component.class.getName());
    }
}

4.2 组件扫描流程

ComponentScanAnnotationParser处理扫描逻辑:

class ComponentScanAnnotationParser {
    
    public Set parse(AnnotationAttributes componentScan,
            String declaringClass) {
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
        
        // 配置扫描器
        configureScanner(scanner, declaringClass, componentScan);
        
        // 执行扫描
        Set basePackages = getBasePackages(componentScan, declaringClass);
        return scanner.doScan(StringUtils.toStringArray(basePackages));
    }
    
    protected void configureScanner(ClassPathBeanDefinitionScanner scanner,
            String declaringClass, AnnotationAttributes componentScan) {
        // 配置排除过滤器
        List typeFilters = new ArrayList<>();
        for (Filter filter : componentScan.getAnnotationArray("excludeFilters", Filter.class)) {
            typeFilters.add(typeFilterFor(filter));
        }
        scanner.addExcludeFilter(new CompositeTypeFilter(typeFilters));
    }
}

五、自动配置条件评估机制

5.1 @Conditional注解体系

SpringBoot的条件注解体系:

@Conditional(OnClassCondition.class)
@Conditional(OnWebApplicationCondition.class)
@Conditional(OnBeanCondition.class)
@Conditional(OnPropertyCondition.class)

5.2 条件评估流程

ConditionEvaluator负责条件评估:

class ConditionEvaluator {
    
    public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
        return shouldSkip(metadata, null);
    }
    
    public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) {
        if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
            return false;
        }
        
        if (phase == null) {
            if (metadata instanceof AnnotationMetadata &&
                    Configuration.class.isAssignableFrom(
                            ((AnnotationMetadata) metadata).getClassName())) {
                return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
            }
            return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
        }
        
        List conditions = new ArrayList<>();
        for (String[] conditionClasses : getConditionClasses(metadata)) {
            for (String conditionClass : conditionClasses) {
                Condition condition = getCondition(conditionClass, this.context.getClassLoader());
                conditions.add(condition);
            }
        }
        
        for (Condition condition : conditions) {
            ConfigurationPhase requiredPhase = null;
            if (condition instanceof ConfigurationCondition) {
                requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
            }
            if ((requiredPhase == null || requiredPhase == phase) &&
                    !condition.matches(this.context, metadata)) {
                return true;
            }
        }
        return false;
    }
}

5.3 OnClassCondition实现

@Order(Ordered.HIGHEST_PRECEDENCE)
class OnClassCondition extends FilteringSpringBootCondition {
    
    @Override
    protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
            AutoConfigurationMetadata autoConfigurationMetadata) {
        List outcomes = new ArrayList<>(autoConfigurationClasses.length);
        for (String autoConfigurationClass : autoConfigurationClasses) {
            String[] onClasses = autoConfigurationMetadata.get(autoConfigurationClass, "ConditionalOnClass");
            if (onClasses != null) {
                outcomes.add(getOutcome(onClasses));
            }
        }
        return outcomes.toArray(new ConditionOutcome[0]);
    }
    
    private ConditionOutcome getOutcome(String[] onClasses) {
        List missing = new ArrayList<>();
        for (String className : onClasses) {
            if (!ClassUtils.isPresent(className, getClass().getClassLoader())) {
                missing.add(className);
            }
        }
        if (!missing.isEmpty()) {
            return ConditionOutcome.noMatch(ConditionMessage
                    .forCondition(ConditionalOnClass.class)
                    .didNotFind("required class", "required classes")
                    .items(Style.QUOTE, missing));
        }
        return ConditionOutcome.match();
    }
}

六、自动配置类加载机制

6.1 spring.factories加载

SpringFactoriesLoader加载自动配置类:

public final class SpringFactoriesLoader {
    
    public static List loadFactoryNames(Class factoryType, @Nullable ClassLoader classLoader) {
        String factoryTypeName = factoryType.getName();
        return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }
    
    private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) {
        MultiValueMap result = cache.get(classLoader);
        if (result != null) {
            return result;
        }
        
        try {
            Enumeration 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);
                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())) {
                        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);
        }
    }
}

6.2 自动配置类处理

AutoConfigurationSorter对自动配置类进行排序:

class AutoConfigurationSorter {
    
    private final AutoConfigurationMetadata autoConfigurationMetadata;
    
    List getInPriorityOrder(Collection classNames) {
        AutoConfigurationClasses classes = new AutoConfigurationClasses(
                this.autoConfigurationMetadata, classNames);
        List orderedClassNames = new ArrayList<>(classNames);
        Collections.sort(orderedClassNames, new Comparator() {
            @Override
            public int compare(String o1, String o2) {
                int i1 = classes.getPriority(o1);
                int i2 = classes.getPriority(o2);
                return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
            }
        });
        return orderedClassNames;
    }
}

七、配置属性绑定机制

7.1 @ConfigurationProperties处理

ConfigurationPropertiesBindingPostProcessor负责属性绑定:

public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProcessor,
        PriorityOrdered, ApplicationContextAware, InitializingBean {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        ConfigurationProperties annotation = getAnnotation(bean, beanName);
        if (annotation != null) {
            bind(bean, beanName, annotation);
        }
        return bean;
    }
    
    private void bind(Object bean, String beanName, ConfigurationProperties annotation) {
        ResolvableType type = getBeanType(bean, beanName);
        String prefix = annotation.prefix();
        Validated validated = getAnnotation(bean, beanName, Validated.class);
        Annotation[] annotations = (validated != null) ?
                new Annotation[] { annotation, validated } : new Annotation[] { annotation };
        Bindable target = Bindable.of(type).withExistingValue(bean)
                .withAnnotations(annotations);
        try {
            this.configurationPropertiesBinder.bind(target, prefix);
        }
        catch (Exception ex) {
            throw new ConfigurationPropertiesBindException(beanName, bean, annotation, ex);
        }
    }
}

7.2 属性源解析

PropertySourcesPlaceholderConfigurer处理占位符:

public class PropertySourcesPlaceholderConfigurer implements
        BeanFactoryPostProcessor, EnvironmentAware {
    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (this.propertySources == null) {
            this.propertySources = (this.environment != null ?
                    this.environment.getPropertySources() : null);
        }
        processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
    }
    
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
            ConfigurablePropertyResolver propertyResolver) throws BeansException {
        propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
        propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
        propertyResolver.setValueSeparator(this.valueSeparator);
        
        StringValueResolver valueResolver = strVal -> {
            String resolved = (this.ignoreUnresolvablePlaceholders ?
                    propertyResolver.resolvePlaceholders(strVal) :
                    propertyResolver.resolveRequiredPlaceholders(strVal));
            if (this.trimValues) {
                resolved = resolved.trim();
            }
            return (resolved.equals(this.nullValue) ? null : resolved);
        };
        
        doProcessProperties(beanFactoryToProcess, valueResolver);
    }
}

八、总结

通过对@SpringBootApplication组合注解的深度解析,我们可以得出以下核心结论:

  1. 组合设计:通过元注解组合实现功能集成,保持单一职责原则
  2. 自动配置:基于条件评估和类路径扫描实现智能自动配置
  3. 扩展机制:通过spring.factories和条件注解提供灵活扩展点
  4. 性能优化:编译时索引和条件缓存提升启动速度
  5. 模块解耦:各功能模块职责清晰,通过标准接口交互

@SpringBootApplication的设计体现了SpringBoot"约定优于配置"的核心理念,通过合理的默认配置和灵活的扩展机制,大大简化了Spring应用的配置工作。理解这些底层机制对于掌握SpringBoot工作原理和进行高级定制开发具有重要意义。

你可能感兴趣的:(#,SpringBoot源码分析,spring,boot,java,spring)