spring源码:@Bean注解解析

目的

在前面的自动扫描bean原理这篇文章中,主要说的是spring是如何将@ComponentScan注解声明的包下,加了@Component注解的业务类扫描到spring容器中的;在这篇文章中,没有说明一个知识点,在这里说明一下:
spring将业务类转换为BeanDefinition的方式有三种

  1. @ComponentScan注解+@Component注解
  2. @Bean
  3. @Import注解,引入ImportBeanDefinitionRegistrar和ImportSelector的实现类
    这是我目前通过源码学习,总结出来的,当然,也有可能不全,后面学习到了 再来这里补充
    本文,就是要说明第二种对业务bean进行转换beanDefinition的源码解析,我不确定自己能不能把这个知识点讲解清楚,试一下吧

源码

在这里插入图片描述
这个gif是我们今天要说的源码,前面的调用逻辑,这里其实就是要调用到

org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

这个方法的逻辑;该方法是什么时候执行到的,为什么要执行这个方法,我在上篇博客中有写到;这里我们只关心@Bean的处理逻辑:

我们来看上个gif最后调用的方法

org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)

public void parse(Set<BeanDefinitionHolder> configCandidates) {
   
	this.deferredImportSelectors = new LinkedList<>();
	for (BeanDefinitionHolder holder : configCandidates) {
   
		BeanDefinition bd = holder.getBeanDefinition();
		try {
   
			/**
			 * 根据beanDefinition的不同来做不同的处理
			 * 如果bean是配置类(加了@Configuration注解的配置类),那这里就会走下面的第一个分支的判断条件
			 * 因为在将配置类放到beanDefinitionMap中的时候,是将配置类声明为了AnnotatedGenericBeanDefinition类型的
			 */
			if (bd instanceof AnnotatedBeanDefinition) {
   
				/**
				 *  如果将bean存入到beanDefinitionMap第四步
				 *
				 *  在这里注入的只是普通的bean,普通的bean 就是指加了@Component注解的bean
				 *  何为不普通的bean? @Bean  各种beanFactoryPostProcessor获取到的bean不在这里注入  但是是在这里解析  只是不是在这里put到BeanDefinitionMap中的
				 */
				parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
			}
			else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
   
				parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
			}
			else {
   
				parse(bd.getBeanClassName(), holder.getBeanName());
			}
		}
	}
	processDeferredImportSelectors();
}

这里会根据beanDefinition的不同类型,来进行不同的处理;由于这里的configCandidates是配置类,所以是AnnotatedBeanDefinition,因为在前面调用AnnotationConfigApplicationContext构造方法的时候,会把配置类注入到BeanDefinitionMap中,创建的是AnnotatedGenericBeanDefinition类型的
在这里插入图片描述

parse()方法中,会执行以下的调用链,中间的一些细节,我们暂时不做解析,我们来看doProcessConfigurationClass()方法
org.springframework.context.annotation.ConfigurationClassParser#parse(org.springframework.core.type.AnnotationMetadata, java.lang.String)
	org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
		org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
		throws IOException {
   

	// Process any @ComponentScan annotations
	/**
	 * 序号1:
	 * 判断类中是否加了@ComponentScan注解
	 *  从matedata 里面拿出@ComponentScan注解的属性信息,在后面的方法中,从这个属性里面获取到value,也就是要扫描的包进行注入
	 */
	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) {
   
			// The config class is annotated with @ComponentScan -> perform the scan immediately
			/**
			 *  如果将bean存入到beanDefinitionMap第6步
			 *
			 *  扫描所有的普通类
			 *  当这个方法执行完之后,将配置类上@ComponentScan要注入的bean已经注入到map中了
			 *  但是如果配置类有@Import的话,是在下面processImports()完成的
			 *
			 *  这里是获取到当前配置类下的所有的要扫描的包路径信息
			 */
			Set<BeanDefinitionHolder> scannedBeanDefinitions =
					this<
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值