继SpringBoot学习笔记(二) 整合redis+mybatis+Dubbo,本篇文章我们开始分析SpringBoot的自动装配原理。
前面已经介绍了Spring的加载过程,经历扫描配置文件--收集beanName--实例化bean这几步,SpringBoot同样如此,源于Spring,高于Spring,省去了”简单模式(特殊场景如多数据源引入,需要额外的单独配置)下xml配置文件的繁琐过程。下面让我们来揭秘SpringBoot的自动装配原理。
1.先从run方法进入,
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2.进入到run方法中
public static ConfigurableApplicationContext run(Class> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
3.最后点到这里
4.继续深入
private void refreshContext(ConfigurableApplicationContext context) {
this.refresh((ApplicationContext)context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
} catch (AccessControlException var3) {
;
}
}
}
5.进入到refresh
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();
}
6.继续进入方法
org.springframework.context.support.AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory); //看这里
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
7.进入到invokeBeanFactoryPostProcessors方法内部
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//这里
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 这里
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
8.继续进入
private static void invokeBeanDefinitionRegistryPostProcessors(Collection extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
9.进入到postProcessor.postProcessBeanDefinitionRegistry(registry)方法
10.看这里
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
} else if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
} else {
this.registriesPostProcessed.add(registryId);
this.processConfigBeanDefinitions(registry);
}
}
11.看最后一句this.processConfigBeanDefinitions(registry) 进入该方法
调试程序发现
这里有我们熟悉的RedisTemplateAutoConfiguration类
并且在上一步中
就已经读读出了配置类。
这里注意:
configClasses获取的是starts中依赖的组件,用rabbitmq举例,组件中如果不对其进行引用那么config中是没有相关类信息的,相反,如果对rabbitmq进行引用则可以加载。
============以下是分析如何从spring.factories中加载XXXAutoConfigration的过程============
12.继续,configClasses的具体读取应该是在parser.parse(candidates)
进入方法中
public void parse(Set configCandidates) {
Iterator var2 = configCandidates.iterator();
while(var2.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
} else {
this.parse(bd.getBeanClassName(), holder.getBeanName());
}
} catch (BeanDefinitionStoreException var6) {
throw var6;
} catch (Throwable var7) {
throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
}
}
this.deferredImportSelectorHandler.process();
}
13.随便点到一个this.parse方法中
protected void processConfigurationClass(ConfigurationClass configClass, Predicate filter) throws IOException {
if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
ConfigurationClass existingClass = (ConfigurationClass)this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
return;
}
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass, filter);
do {
// 点这里
sourceClass = this.doProcessConfigurationClass(configClass, sourceClass, filter);
} while(sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
}
14.this.doProcessConfigurationClass(configClass, sourceClass, filter);
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
// 在这递归的,会回到上一步代码中
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @Import annotations
// 看这个名字可以知道这个方法的作用
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
}
getImports(sourceClass)方法是一个递归调用,用来收集Import注解。
15.继续看processImports方法
org.springframework.context.annotation.ConfigurationClassParser#processImports
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection importCandidates, Predicate exclusionFilter,
boolean checkForCircularImports) {
...
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class> candidateClass = candidate.loadClass();
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate selectorFilter = selector.getExclusionFilter();
if (selector instanceof DeferredImportSelector) {
// 因为AutoConfigurationImportSelector继承了DeferredImportSelector,所以会进入这个方法,放到
// 列表里处理,直接放到一个List中。
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
}
}
...
}
}
}
16.org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#handle
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
if (this.deferredImportSelectors == null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
}
else {
this.deferredImportSelectors.add(holder);
}
}
17.org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#register
代码
public void register(DeferredImportSelectorHolder deferredImport) {
// AutoConfigurationImportSelector返回的是AutoConfigurationGroup.class,代码中已写死
Class extends Group> group = deferredImport.getImportSelector().getImportGroup();
// 封装成 DeferredImportSelector.Group 对象,并放到了groupings中,groupings是LinkedHashMap
// Group对象是用AutoConfigurationGroup.class生成
DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
(group != null ? group : deferredImport),
key -> new DeferredImportSelectorGrouping(createGroup(group)));
grouping.add(deferredImport);
this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getConfigurationClass());
}
18.org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports
方法,SpringSPI的调用点=
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
Predicate exclusionFilter = grouping.getCandidateFilter();
//遍历放入到grouping中的group,并执行getImports()方法,此方法就是SPI调用点!!!!
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter, false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}
19.org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGrouping#getImports 方法
public Iterable getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
// 调用group的process方法
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}
20.org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
// 调用getAutoConfigurationEntry
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
如上所示,最终来到
21.org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry
该方法可以从spring.factories读取相应配置。
============以上是分析如何从spring.factories中加载XXXAutoConfigration的过程============
好,我们继续。
============以下是将configClasses中的XXXAutoConfigration注册为Bean的过程============
22.回到步骤11.org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
public void loadBeanDefinitions(Set configurationModel) {
ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator = new ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator();
Iterator var3 = configurationModel.iterator();
while(var3.hasNext()) {
ConfigurationClass configClass = (ConfigurationClass)var3.next();
this.loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
23.org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
// 此处打上断点configClass.getResource().toString().contains("Rabbit")
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
} else {
// 此处打上断点configClass.getResource().toString().contains("Rabbit")
if (configClass.isImported()) {
this.registerBeanDefinitionForImportedConfigurationClass(configClass);
}
Iterator var3 = configClass.getBeanMethods().iterator();
while(var3.hasNext()) {
BeanMethod beanMethod = (BeanMethod)var3.next();
//这里处理对应的@Bean方法 !!!!!!!!!!!!!!!!!!!!
this.loadBeanDefinitionsForBeanMethod(beanMethod);
}
this.loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
this.loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
}
执行完this.registerBeanDefinitionForImportedConfigurationClass(configClass);看目前的BeanNames
24.继续org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
//注册
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
注册完成以后效果
============以上是将configClasses中的XXXAutoConfigration注册为Bean的过程============
可以看到,不仅RabbitAutoConfiguration中的RabbitConnectionFactoryCreator成功注册,rabbitconnectionFactory也进行了注册(rabbitConnectionFactory的注册时机在哪里困扰了博主很久,在这里恍然大悟)。
实例化具体过程参考: Spring源码解析(五)IOC源码
以上就是SpringBoot自动装配的全部过程。