springboot 自动装配

一般我们启动一个项目只需要再启动类上面增加@SpringBootApplication 注解,就能自动的装备bean对象,原理是什么呢? 下面从

SpringApplication.run() 开始进行解析一下

从上图中我们很容易就进入到了SpringApplication.run()方法中, 注意我上述框起来的两行代码分别是创建上下文和刷新上下文

创建上下文 this.createApplicationContext

从上述源码中,我们可以知道spring 通过反射的方式创建了一个Context, 可以根据WebApplicationType创建指定的上下文, 这里以AnnotationConfigServletWebServerApplicationContext为例子,进入源码

AnnotationConfigServletWebServerApplicationContext

在这个上下文中,可以看到这里创建了两个对象, 一个是根据注解的Reader 和 根据路径的Scanner,并且传入了自身的上下文引用

从上面两图中,我们可以看见帮助可上下文注册了BeanFactory 的后置处理器, 比如框住的部分就是增加了ConfigurationClassPostProcessor后置处理器

更新上下文this.refreshContext(context)

在更新上下文的时候,最终会进入到AbstractApplicationContextrefresh 方法中,如下图所示

invokeBeanFactoryPostProcessors

invokeBeanFactoryPostProcessors是一个BeanFactory 类型的后置处理方法,在该方法获取所有注册的BeanFactoryPostProcessor,并且执行postProcessBeanFactory方法,代码如下图

// AbstractApplicationContext# invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
        .......
    }

// PostProcessorRegistrationDelegate# invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
       .......
        invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        .......
    }

// PostProcessorRegistrationDelegate# invokeBeanFactoryPostProcessors
    private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
        Iterator var2 = postProcessors.iterator();
        while(var2.hasNext()) {
            BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next();
            postProcessor.postProcessBeanFactory(beanFactory);
        }
    }

如上图代码所示, 最终会执行BeanFactoryPostProcessor.postProcessBeanFactory, 还记得在创建上下文中我们最后一张图,我们注册了一些BeanFactoryPostProcessor吗? 就以ConfigurationClassPostProcessor 为例,在执行postProcessBeanFactory时,进入该方法,最后调用processConfigBeanDefinitions进行解析和注册BeanDefinitions

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		.... 省略
        if (!this.registriesPostProcessed.contains(factoryId)) {
            this.processConfigBeanDefinitions((BeanDefinitionRegistry)beanFactory);
        }
    }


public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {  
    ......		
    Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
    HashSet alreadyParsed = new HashSet(configCandidates.size());

    do {
        // 解析
        parser.parse(candidates);  
        Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
		.....
		....
        // 注册
        this.reader.loadBeanDefinitions(configClasses);
		...
    }
    }

在进入parse()方法,实际上是进入到ConfigurationClassParser.parse

ConfigurationClassParser.parse
public void parse(Set<BeanDefinitionHolder> configCandidates) {
    this.deferredImportSelectors = new LinkedList<>();

    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            if (bd instanceof AnnotatedBeanDefinition) {
                // 对于每个有注解的类,都执行方法parse(AnnotationMetadata metadata, String beanName)
                parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
            }
            ...
                catch (BeanDefinitionStoreException ex) {
                    ...
                }
        }
        //后续处理DeferredImportSelector的实现类
        processDeferredImportSelectors();
    }
    
    
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        processConfigurationClass(new ConfigurationClass(metadata, beanName));
    }
    

    
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		.... 省略
		do {
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);
		.... 省略

ConfigurationClassParser.doProcessConfigurationClass

经过多次调用,最终调用了doProcessConfigurationClass方法,在该方法中针对不同的注解类型, 执行了不同的注解执行方法,比如针对启动类中@ComponentScan 注解, 这里会直接执行,扫描指定包下面对象并封装成BeanDefinitionHolder,还有一个需要关注的是@Import 装配processImports方法

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {

		// 执行 @PropertySource 注解
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				....
		}

		// Process any @ComponentScan annotations
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// 配置类使用 @ComponentScan 注解 -> 立即执行扫描
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
                    this.componentScanParser.parse(componentScan,sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		//  执行 @Import 注解
		processImports(configClass, sourceClass, getImports(sourceClass), true);

		//  执行 @ImportResource 注解
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

		// 处理 @Bean methods
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// 处理接口中的默认方法
		processInterfaces(configClass, sourceClass);

		// 执行父类,如果存在
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// No superclass -> processing is complete
		return null;
	}
ConfigurationClassParser.processImports

这里省略了其他代码,只留下关键代码selector.selectImports, 在@EnableAutoConfiguration 注解中, @Import({AutoConfigurationImportSelector.class}) 有这么一个注解, 因此,这里selector.selectImports调用的实际上是AutoConfigurationImportSelector.selectImports 方法

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, boolean checkForCircularImports) {

			...... 省略其他代码
			String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
			Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
			...... 省略其他代码			
	}
AutoConfigurationImportSelector.selectImports

在进入到selectImports 后,调用了getCandidateConfigurations,最终调用到了SpringFactoriesLoader.loadSpringFactories 方法

SpringFactoriesLoader.loadSpringFactories

根据代码我们可以发现, 最终类加载器会从META-INF/spring.factories中获取所有全类限定名,便可提供给上层方法进行获取,最后创建对应的BeanDefinition对象,在后面Bean的实例化过程中,便可实现自动装配了

posted @   苜蓿椒盐  阅读(998)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示