之前的文章中分析了springboot启动的大概流程,那些只是冰山一角,最关键的refresh()
只是一笔带过。这篇文章中将会提到refreh
的部分过程。另外之前的文章也写过springboot如何自定义starter
,这篇文章将简单分析一下其原理。
在 spring源码阅读(一) 中说到的第四步:spring容器前置处理 中,将我们的启动类HelloWorldApplication.class
当做参数调用load()
,使其加载到beanDefinitionMap
中。
1 2 3 4 5 6 7 8 9 10 11 12 private int load (Class<?> source) { if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) { GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class); load(loader); } if (isComponent(source)) { this .annotatedReader.register(source); return 1 ; } return 0 ; }
这次我们再跟进去看看,最后调用的地方是AnnotatedBeanDefinitionReader.java
的doRegisterBean()
方法。进入断点查看,我们的启动类最终被包装成AnnotatedGenericBeanDefinition
,后期的启动类的处理都基于该对象了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 private <T> void doRegisterBean (Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition (beanClass); if (this .conditionEvaluator.shouldSkip(abd.getMetadata())) { return ; } abd.setInstanceSupplier(supplier); ScopeMetadata scopeMetadata = this .scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this .beanNameGenerator.generateBeanName(abd, this .registry)); AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); if (qualifiers != null ) { for (Class<? extends Annotation > qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true ); } else if (Lazy.class == qualifier) { abd.setLazyInit(true ); } else { abd.addQualifier(new AutowireCandidateQualifier (qualifier)); } } } if (customizers != null ) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder (abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this .registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this .registry); }
@EnableAutoConfiguration @SpringBootApplication
注解中包含了自动配置入口的注解。
1 2 3 4 5 6 7 8 9 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {}
跟进去看一下,又包含了@AutoConfigurationPackage
自动配置包注解
1 2 3 4 5 6 7 8 9 10 11 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration" ; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
@AutoConfigurationPackage 跟进@AutoConfigurationPackage,它导入了
AutoConfigurationPackages.Registrar.class`
1 2 3 4 5 6 7 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage {}
跟进它 import 的这个类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 static class Registrar implements ImportBeanDefinitionRegistrar , DeterminableImports { @Override public void registerBeanDefinitions (AnnotationMetadata metadata, BeanDefinitionRegistry registry) { register(registry, new PackageImport (metadata).getPackageName()); } @Override public Set<Object> determineImports (AnnotationMetadata metadata) { return Collections.singleton(new PackageImport (metadata)); } }
如果我们将断点打在registerBeanDefinitions
方法里,可以看见这一步是refresh()
过程中的invokeBeanFactoryPostProcessors(beanFactory)
方法在调用。
执行完后 registry 中 beanDefinitionMap 将多一个 AutoConfigurationPackages
@Import(AutoConfigurationImportSelector.class) 导入哪些组件的选择器,将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中。进入此类,有一个关键方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 protected AutoConfigurationEntry getAutoConfigurationEntry (AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = filter(configurations, autoConfigurationMetadata); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry (configurations, exclusions); }
如果在这个方法里打断点,可以发现,这里也是 refresh()
过程中的invokeBeanFactoryPostProcessors(beanFactory)
方法在调用。
接着重点看下getCandidateConfigurations()
方法,它从META-INF/spring.factories
文件中取出EnableAutoConfiguration
对应的所有 value。因此,如果要实现自动配置功能,需要将我们的自动配置类写在 factories 文件下的 org.springframework.boot.autoconfigure.EnableAutoConfiguration属性中
1 2 3 4 5 6 7 8 9 10 11 protected List<String> getCandidateConfigurations (AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> 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; }
更详细的 refresh 过程,将在下一篇文章中分析。