SpringBoot源码分析一(自动装配原理)
什么是Spring Boot特点maven依赖入口@SpringBootApplication@SpringBootConfiguration@EnableAutoConfiguration
@AutoConfigurationPackage@import(AutoConfigurationimportSelector.class) 核心方法:总结:
官网:https://spring.io/projects/spring-boot
目前最新版本为 2.6.2
简介:来自官网第一句话。
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.
Spring Boot 可以轻松创建独立的、生产级的基于 Spring 的应用程序,您可以“直接运行”这些应用程序。
大多数 Spring Boot 应用程序需要最少的 Spring 配置。
什么是Spring Boot它使用 “习惯优于配置” (项目中存在大量的配置,此外还内置一个习惯性的配置,让你无须手动配置)的理念让你的项目快速运行起来。它并不是什么新的框架,而是默认配置了很多框架的使用方式,就像 Maven 整合了所有的 jar 包一样,Spring Boot 整合了所有框架 特点
创建独立的 Spring 应用程序直接嵌入Tomcat、Jetty或Undertow(无需部署WAR文件)提供自以为是的“入门”依赖项以简化您的构建配置尽可能自动配置 Spring 和 第三方库提供生产就绪功能,例如指标、运行状况检查和外部化配置完全不需要代码生成,也不需要 XML 配置 maven依赖
入口4.0.0 org.example springboot-test1.0-SNAPSHOT org.springframework.boot spring-boot-starter-web2.6.2
@SpringBootApplication @RestController public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } @GetMapping("") public String hello(@RequestParam(value = "name", defaultValue = "World") String name) { return String.format("Hello %s!", name); } }@SpringBootApplication
这个注解标注于某个类上,说明这个类是Spring Boot的主配置类,通过运行这个类的 main 方法来启动 Spring Boot。
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {}@SpringBootConfiguration
Spring Boot的配置类标注在某个类上,表示这是一个Spring Boot的配置类
注解定义如下:
@Configuration public @interface SpringBootConfiguration {}
其实就是一个Configuration配置类,意思是 MyApplication 最终会被注册到Spring容器中
@EnableAutoConfiguration开启自动配置功能以前使用Spring需要配置的信息,Spring Boot帮助自动配置;@EnableAutoConfiguration通知SpringBoot开启自动配置功能,这样自动配置才能生效。
注解定义如下:
@AutoConfigurationPackage @import(EnableAutoConfigurationimportSelector.class) public @interface EnableAutoConfiguration {}@AutoConfigurationPackage
自动配置包注解
@import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage {}
@import(AutoConfigurationPackages.Registrar.class):默认将主配置类(@SpringBootApplication)所在的包及其子包里面的所有组件扫描到Spring容器中。如下
static class Registrar implements importBeanDefinitionRegistrar, Determinableimports { @Override public void registerBeanDefinitions(Annotationmetadata metadata, BeanDefinitionRegistry registry) { // 默认将会扫描@SpringBootApplication标注的主配置类所在的包及其子包下所有组件 register(registry, new Packageimports(metadata).getPackageNames().toArray(new String[0])); } @Override public Set@import(AutoConfigurationimportSelector.class)
EnableAutoConfigurationimportSelector: 导入哪些组件的选择器,将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中
@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) { ... Listconfigurations = getCandidateConfigurations(annotationmetadata, attributes); ... }
getCandidateConfigurations() 方法会给容器中注入众多的自动配置类(xxxAutoConfiguration),就是导入这个场景所需要的所有组件,并配置好这些组件。
protected ListgetCandidateConfigurations(Annotationmetadata metadata, AnnotationAttributes attributes) { List 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; }
loadFactoryNames() 从类路径的meta-INF/spring.factories中加载所有默认的自动配置类
public static final String FACTORIES_RESOURCE_LOCATION = "meta-INF/spring.factories"; public static ListloadFactoryNames(Class> factoryType, @Nullable ClassLoader classLoader) { ...... return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList()); } private static Map > loadSpringFactories(ClassLoader classLoader) { Map > result = cache.get(classLoader); if (result != null) { return result; } result = new HashMap<>(); try { // 获取加载所有默认的自动配置类 Enumeration urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION); while (urls.hasMoreElements()) { URL url = urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); ...... // Replace all lists with unmodifiable lists containing unique elements result.replaceAll((factoryType, implementations) -> implementations.stream().distinct() .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList))); cache.put(classLoader, result); } catch (IOException ex) { throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } return result; }
SpringBoot启动的时候从类路径下的 meta-INF/spring.factories中获取EnableAutoConfiguration指定的值,并将这些值作为自动配置类导入到容器中,自动配置类就会生效,最后完成自动配置工作。EnableAutoConfiguration默认在spring-boot-autoconfigure这个包中。
在这里插入图片描述
最终有96个自动配置类被加载并注册进Spring容器中。
J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-xxx.jar中。在这些自动配置类中会通过@ConditionalOnClass等条件注解判断是否导入了某些依赖包,从而通过@Bean注册相应的对象进行自动配置。后面我们会有单独文章讲自动配置的内容
@ConditionalOnBean // 当给定的在bean存在时,则实例化当前Bean @ConditionalOnMissingBean // 当给定的在bean不存在时,则实例化当前Bean @ConditionalOnClass // 当给定的类名在类路径上存在,则实例化当前Bean @ConditionalOnMissingClass // 当给定的类名在类路径上不存在,则实例化当前Bean核心方法:
selectimports() -> getAutoConfigurationEntry() -> getCandidateConfigurations() -> SpringFactoriesLoader.loadFactoryNames() -> loadSpringFactories()
总结:路径上存在,则实例化当前Bean
@ConditionalOnMissingClass // 当给定的类名在类路径上不存在,则实例化当前Bean
## 核心方法: selectimports() -> getAutoConfigurationEntry() -> getCandidateConfigurations() -> SpringFactoriesLoader.loadFactoryNames() -> loadSpringFactories() ## 总结: > SpringBoot启动的时候通过@EnableAutoConfiguration注解找到meta-INF/spring.factories文件中的所有自动配置类,并对其加载,这些自动配置类都是以AutoConfiguration结尾来命名的。它实际上就是一个JavaConfig形式的IOC容器配置类,通过以Properties结尾命名的类中取得在全局配置文件中配置的属性,如server.port。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)