@SpringBootApplication注解是SpringBoot应用的核心入口注解,它实际上是一个组合注解(Composite Annotation),集成了SpringBoot自动配置的核心功能。本文将深入剖析@SpringBootApplication注解的底层实现原理,从元注解解析、自动配置机制到组件扫描流程,全面解析SpringBoot启动的核心魔法。通过本文,读者将透彻理解SpringBoot自动配置的工作机制及其底层实现细节。
@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 extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
@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注解支持编译时索引,加速组件扫描。
@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 {};
}
@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
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;
}
}
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(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
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;
}
}
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());
}
}
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));
}
}
SpringBoot的条件注解体系:
@Conditional(OnClassCondition.class)
@Conditional(OnWebApplicationCondition.class)
@Conditional(OnBeanCondition.class)
@Conditional(OnPropertyCondition.class)
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;
}
}
@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();
}
}
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);
}
}
}
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;
}
}
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);
}
}
}
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组合注解的深度解析,我们可以得出以下核心结论:
@SpringBootApplication的设计体现了SpringBoot"约定优于配置"的核心理念,通过合理的默认配置和灵活的扩展机制,大大简化了Spring应用的配置工作。理解这些底层机制对于掌握SpringBoot工作原理和进行高级定制开发具有重要意义。