0


《深入探究 @SpringBootApplication 注解的内部原理》

《深入探究 @SpringBootApplication 注解的内部原理》

@SpringBootApplication

注解涵盖了 Spring Boot 的包扫描原理、自动装配原理等众多重要原理。接下来,我们将对该注解展开深入且详尽的研究。而研究上述原理的关键,在于剖析

@SpringBootApplication

内部的构成结构,如下图:

1723956831160

下面对@SpringBootConfiguration和@EnableAutoConfiguration进行详解。

一、@SpringBootConfiguration注解

内部结构:

1723956978015

@Configuration是Spring的一个注解,其修饰的类会加入Spring容器。这就说明SpringBoot的启动类会加入Spring容器。

进入内部:

1723957021487

该注解会被注入到IOC容器中

二、@EnableAutoConfiguration注解

内部结构:

1723957221490

@AutoConfigurationPackage注解:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Import(AutoConfigurationPackages.Registrar.class)public@interfaceAutoConfigurationPackage{}

其内部@Import进来的类AutoConfigurationPackages.Registrar类:

源码如下:

staticclassRegistrarimplementsImportBeanDefinitionRegistrar,DeterminableImports{@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry){register(registry,newPackageImport(metadata).getPackageName());}@OverridepublicSet<Object>determineImports(AnnotationMetadata metadata){returnCollections.singleton(newPackageImport(metadata));}}

进入registerBeanDefinitions方法中的register方法:

publicstaticvoidregister(BeanDefinitionRegistry registry,String... packageNames){if(registry.containsBeanDefinition(BEAN)){BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
            constructorArguments.addIndexedArgumentValue(0,addBasePackages(constructorArguments, packageNames));}else{GenericBeanDefinition beanDefinition =newGenericBeanDefinition();
            beanDefinition.setBeanClass(BasePackages.class);
            beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
            beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registry.registerBeanDefinition(BEAN, beanDefinition);}}

通过断点,查看packageNames参数的传入值:

1723957491816

可见是在启动类中配置的scanBasePackages属性的包。
程序进入了else条件块儿,执行如下代码:

GenericBeanDefinition beanDefinition =newGenericBeanDefinition();
            beanDefinition.setBeanClass(BasePackages.class);
            beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
            beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registry.registerBeanDefinition(BEAN, beanDefinition);

该步骤就是创建BeanDefinition对象,然后将其注册到BeanDefinition注册器中,详情如下:

1723957712367

可以看到,这个BeanDefinition封装的是一个Package对象。所以,BeanDefinition不只能封装类的属性,还可以封装整个包的属性。
@Import(AutoConfigurationImportSelector.class):

进入AutoConfigurationImportSelector类:

AutoConfigurationImportSelector

是自动配置的关键类。其主要功能是选择需要导入的自动配置类。

1.选择配置类:通过

selectImports()

方法确定需要导入的自动配置类。

1723959187034

2.加载配置条目:调用

getAutoConfigurationEntry()

方法来加载自动配置类的元数据。

1723959241908

集合configurations长度为145,所以共有145个配置类可以选择,在使用时返回对应需要的配置类

3.解析配置类:通过

getCandidateConfigurations()

方法从

spring.factories

文件中加载所有可用的自动配置类,源码如下:

protectedList<String>getCandidateConfigurations(AnnotationMetadata metadata,AnnotationAttributes attributes){List<String> configurations =newArrayList<>(SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader()));ImportCandidates.load(AutoConfiguration.class,getBeanClassLoader()).forEach(configurations::add);Assert.notEmpty(configurations,"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "+"are using a custom packaging, make sure that file is correct.");return configurations;}

我们进入到getCandidateConfigurations()方法中可以看到是使用SpringFactoriesLoader从spring.factories文件中加载指定类型的工厂类名,然后通过ImportCandidates.load方法加载所有AutoConfiguration类,并将这些类名添加到列表中。

SpringFactoriesLoader详解
SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置,源码如下:

1723958420241

它配合@EnableAutoConfiguration使用的话,它更多是提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类

1723958497146

所以,@EnableAutoConfiguration自动配置:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

总结:

Spring Boot 的自动配置机制凭借 @EnableAutoConfiguration 注解与 AutoConfigurationImportSelector 类,达成了对 spring.factories 文件里所定义的自动配置类的智能化加载。此机制使开发者能够将精力集中于业务逻辑,无需在基础框架配置上耗费过多心思,大幅提升了开发效率,增强了代码的可维护性。

经由本文的阐述,您应当能够更透彻地领会 Spring Boot 自动配置隐藏在背后的技术要点,并且能够更为高效地运用这一特性来搭建自身的应用。

标签: java 开发语言

本文转载自: https://blog.csdn.net/qq_67028830/article/details/141300257
版权归原作者 Nonullpoint. 所有, 如有侵权,请联系我们删除。

“《深入探究 @SpringBootApplication 注解的内部原理》”的评论:

还没有评论