之前的文章中分析了springboot启动的大概流程,那些只是冰山一角,最关键的refresh()
只是一笔带过。这篇文章中将会提到refreh
的部分过程。另外之前的文章也写过springboot如何自定义starter
,这篇文章将简单分析一下其原理。
在 spring源码阅读(一)中说到的第四步:spring容器前置处理中,将我们的启动类HelloWorldApplication.class
当做参数调用load()
,使其加载到beanDefinitionMap
中。
1 | private int load(Class<?> source) { |
这次我们再跟进去看看,最后调用的地方是AnnotatedBeanDefinitionReader.java
的doRegisterBean()
方法。进入断点查看,我们的启动类最终被包装成AnnotatedGenericBeanDefinition
,后期的启动类的处理都基于该对象了。
1 | private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, |
@EnableAutoConfiguration
@SpringBootApplication
注解中包含了自动配置入口的注解。
1 | (ElementType.TYPE) |
跟进去看一下,又包含了@AutoConfigurationPackage
自动配置包注解
1 | (ElementType.TYPE) |
@AutoConfigurationPackage
跟进@AutoConfigurationPackage,它导入了
AutoConfigurationPackages.Registrar.class`
1 | (ElementType.TYPE) |
跟进它 import 的这个类
1 | static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { |
如果我们将断点打在registerBeanDefinitions
方法里,可以看见这一步是refresh()
过程中的invokeBeanFactoryPostProcessors(beanFactory)
方法在调用。
执行完后 registry 中 beanDefinitionMap 将多一个 AutoConfigurationPackages
@Import(AutoConfigurationImportSelector.class)
导入哪些组件的选择器,将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中。进入此类,有一个关键方法:
1 | protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, |
如果在这个方法里打断点,可以发现,这里也是 refresh()
过程中的invokeBeanFactoryPostProcessors(beanFactory)
方法在调用。
接着重点看下getCandidateConfigurations()
方法,它从META-INF/spring.factories
文件中取出EnableAutoConfiguration
对应的所有 value。因此,如果要实现自动配置功能,需要将我们的自动配置类写在 factories 文件下的 org.springframework.boot.autoconfigure.EnableAutoConfiguration属性中
1 | protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { |
更详细的 refresh 过程,将在下一篇文章中分析。