1. @SpringBootApplication
- @SpringBootApplication 组合注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(...)
public @interface SpringBootApplication {}
1.3 拆分示例
将 SpringBoot 启动类拆分为两个独立的Java类
@Configuration
@EnableAutoConfiguration
@Component Scan
public class DemoConfiguration {
@Bean
public Controller controller() {
return new Controller();
}
}
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoConfiguration.class, args);
}
}
2. @SpringBootConfiguration
- 包含 @Configuration, 代表启动类就是一个配置类
3. @ComponentScan
- 扫描包
4. @EnableAutoConfiguration
- 实现自动装配
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
4.1 @AutoConfigurationPackage
- 自动配置包,指定默认的包规则
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
利用 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<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
4.2 AutoConfigurationImportSelector.class
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
// ...
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
}
}
1. AutoConfigurationImportSelector.getAutoConfigurationEntry(annotationMetadata)
2. AutoConfigurationImportSelector.getCandidateConfigurations(annotationMetadata, attributes)
3. SpringFactoriesLoader.loadFactoryNames
4. SpringFactoriesLoader.loadSpringFactories
4.1 Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
4.2 FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
- 利用 getAutoConfigurationEntry(annotationMetadata) 给容器中批量导入组件
- 调用 getCandidateConfigurations(annotationMetadata, attributes) 获取所有需要导入容器的配置类
- 利用工厂加载loadSpringFactories() 获取所有组件
- 从 META-INF/spring.factories 加载
5. 按需开启自动配置项
- 自动配置功能在 spring-boot-autoconfigure 包里
- 按照条件装配规则(@Conditional) 按需配置
分析类 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration {}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration {}
}
6. SpringFactoriesLoader 类
- SpringBoot 项目启动时,SpringFactoriesLoader 类(在 spring-core.jar)
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
// ...
for (String factoryImplementationName : factoryImplementationNames) {
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
AnnotationAwareOrderComparator.sort(result);
return result;
}
}
在 spring-boot-autoconfigure.jar 的 spring.factories 文件里配置了 WebMvcAutoConfiguration
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
查看 WebMvcAutoConfiguration 类,实际是由 DispatcherServletAutoConfiguration 类实现加载
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {}
网友评论