众所周知 SpringBoot 集成了一系列的配置文件与配置类,旨在帮助开发者快速上手开发,做到 You can just run。本文将就 SpringBoot 如何实现自动装配 @SpringBootApplication 同级路径下所有 @Component 的注册与对应 `org.springframework.web.servlet.DispatcherServlet` 中 Controller 切面的填充做一简单的探寻。
@SpringBootApplicationSpringBoot 的核心启动类兼具装配 bean 与加载注解配置的功能,这一点从注解自身构造不难得出(节选部分代码):
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {}
其中,@ComponentScan 为包扫描注解,在这里配置了排除的扫描种类,而 @SpringBootConfiguration 展开来看仅为 @Configuration 标注的一子级配置注解,代表以 @SpringBootApplication 标注的类也同为注解配置类,Spring 将对其进行一系列的注解配置解析(以下为 @SpringBootConfiguration 注解部分)。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @documented @Configuration @Indexed public @interface SpringBootConfiguration {}@EnableAutoConfiguration
顾名思义,我们不难猜测到使用这个注解标注即会触发自动装配的功能,我们先展开看一下它的注解结构:
@AutoConfigurationPackage @import(AutoConfigurationimportSelector.class) public @interface EnableAutoConfiguration {}自动装配包 - @AutoConfigurationPackage
一看名字就可以得知,此注解是为了自动装配对应配置类的包路径而存在,我们展开看一下 @AutoConfigurationPackage 的内容
@import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage {}
@import 注解想必大家都非常熟悉,我们在 SpringMVC 中常使用它对 @Configuration 标注的配置类进行导入,但通过翻看源码注释我们可以发现他还有其他的功能,就是导入相应的 importSelector 和 importBeanDefinitionRegistrar:
跳转到 AutoConfigurationPackages.Registrar,我们不难发现这个内部类实现了 importBeanDefinitionRegistrar,该内部类以注解元数据(Annotationdata)Bean 注册实现类(BeanDefinitionRegistry,为一个接口,其实现类有常见的诸如 接口配置上下文加载器 AnnotationConfigApplicationContext 与 Xml 配置上下文加载器 XmlServletWebServerApplicationContext)解析注册了被扫描的包(Package)对象,实现了对启动类下包的自动装配:
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自动装配 bean - @import(AutoConfigurationimportSelector.class)
AutoConfigurationimportSelector 这个类实现了 DeferredimportSelector 接口,即为上述 @import 支持配置的 importSelector 接口的子类,这也是该实现类能被配置进 @import 的根本原因。
阅读源码,我们不难发现 AutoConfigurationimportSelector#process 这个方法,查看对应的接口方法我们可以得知该方法的作用是处理导入的 @Configuration 标注类的接口元数据(Annotationmetadata)。那么在这个方法中,理应存在我们要找寻的自动装配的具体实现。
查看实现类方法,我们可以看到以下一行获取自动配置条目(AutoConfigurationEntry)的内部方法:
转到对应方法,我们不难在其中发现这样一行所谓 获取候选配置文件——即自动装配默认配置的方法 getCandidateConfigurations。在获取配置之后注册对应的加载事件(fireAutoConfigurationimportEvents)即是全部自动装配 bean 的流程。
思考至此,自动装配的逻辑实现便告一段落了,但我们仍有疑问——默认配置类在哪?带着这个疑问,我们点开了 getCandidateConfigurations 方法,发现真正的答案还得去 SpringFactoriesLoader 中寻找:
跳转到 SpringFactoriesLoader#loadFactoryNames,查看方法注解我们得知,所有定义的默认工厂实现都在 "meta-INF/spring.factories" 这个文件中配置,找到 spring-boot-autoconfiguration 包下的该文件,至此得解。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)