SpringBoot 自动配置原理以及启动流程

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@Import(AutoConfigurationPackages.Registrar.class)

public @interface AutoConfigurationPackage {

}

导入了一个AutoConfigurationPackages.Registrar.class

自动配置包类的静态内部类 注册器类 打个的断点debug

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

//将注解元数据进行注册 getPackageName

@Override

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

register(registry, new PackageImport(metadata).getPackageName());

}

@Override

public Set determineImports(AnnotationMetadata metadata) {

return Collections.singleton(new PackageImport(metadata));

}

}

SpringBoot 自动配置原理以及启动流程

可以发现已经能够获取到****包名

=========================================================================================

说白了就是将主配置类(即@SpringBootApplication标注的类)的所在包及子包里面所有组件扫描加载到Spring容器。所以包名一定要注意。

========================================================================================================================================================

SpringBoot 自动配置原理以及启动流程

@Import(AutoConfigurationImportSelector.class)

==================================================================================================================

进入该类

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,

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 = filter(configurations, autoConfigurationMetadata);

fireAutoConfigurationImportEvents(configurations, exclusions);

return new AutoConfigurationEntry(configurations, exclusions);

}

List configurations = getCandidateConfigurations(annotationMetadata, attributes);

可发现配置都通过这个方法获得

protected List getCandidateConfigurations(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;

}

protected ClassLoader getBeanClassLoader() {

return this.beanClassLoader;

}

//进入SpringFactoriesLoader.loadFactoryNames()方法

public static List loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {

String factoryTypeName = factoryType.getName();

return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());

}

//进入 loadSpringFactories(classLoader)

private static Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader) {

MultiValueMap<String, String> result = cache.get(classLoader);

if (result != null) {

return result;

}

try {

Enumeration urls = (classLoader != null ?

//public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;

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);

}

}

//public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;

List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());

通过ClassLoader加载使用了这个**@EnableAutoConfiguration**注解的类

这个方法会加载jar包中 META-INF/spring.factories 文件中配置的配置对象

SpringBoot 自动配置原理以及启动流程

SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。以前我们需要自己配置的东西,自动配置类都帮我们完成了。

spring.factories文件也是一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔,如下图所示:

SpringBoot 自动配置原理以及启动流程

接下来看看都导入了哪些组件被添加到容器中

selectImports方法

@Override

public String[] selectImports(AnnotationMetadata annotationMetadata) {

if (!isEnabled(annotationMetadata)) {

return NO_IMPORTS;

}

AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader

.loadMetadata(this.beanClassLoader);

AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,

annotationMetadata);

return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());

}

//进入 getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata) 打个断点看看;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

分享

这次面试我也做了一些总结,确实还有很多要学的东西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Cloud实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Boot实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!

[外链图片转存中…(img-utxn5Lh5-1711821755071)]

Spring Cloud实战

[外链图片转存中…(img-3E8ixpQV-1711821755072)]

Spring Boot实战

[外链图片转存中…(img-Egp8RFhQ-1711821755072)]

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值