Spring5源码分析(2)----spring IoC容器的加载过程

1.实例化容器:AnnotationConfigApplicationContext

这里主要分析注解形式的源码,我们启动容器的时候,虽然只是new了一个AnnotationConfigApplicationContext对象,但是在这个过程中spring处理了很多的事情。

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

AnnotationConfigApplicationContext的类结构图:
在这里插入图片描述
创建AnnotationConfigApplicationContext对象

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		//调用构造函数
		this();
		//注册配置类
		register(componentClasses);
		//ioc容器刷新
		refresh();
	}

1.1 构造方法

(1)这是一个有参的构造方法,可以接收多个配置类,不过一般情况下,只会传入一个配置类。
(2)这个配置类有两种情况,一种是传统意义上的带上@Configuration注解的配置类,还有一种是没有带@Configuration,但是带有@Component,@Import,@ImportResouce,@Service, @ComponentScan等注解的配置类,在Spring内部把前者称为Full配置类,把后者称之为Lite配置类。

1.2 this()无参构造方法

无参构造中主要就是对读取器reader和扫描器scanner进行了实例化,reader的类型是AnnotatedBeanDefinitionReader,可以看出它是一个负责注解类型的Bean定义读取器,scanner的类型是ClassPathBeanDefinitionScanner,它仅仅是在外面手动调用.scan方法,或者调用参数为String的构造方法,传入需要扫描的包名才会用到,像这样方式传入的配置类是不会用到这个scanner对象的。

	public AnnotationConfigApplicationContext() {
		//调用本构造方法之前会先去调用父类GenericApplicationContext的构造函数
		/**
		 * 创建一个读取注解的Bean定义的读取器
		 * 完成了spring内部BeanDefinition的注册(主要是后置处理器)
		 */
		this.reader = new AnnotatedBeanDefinitionReader(this);
		/**
		 * 创建BeanDefinition扫描器,可以用来扫描包或者类,继而转换成bean定义
		 *
		 * spring默认的扫描包不是这个scanner对象,而是自己new的一个ClassPathBeanDefinitionScanner
		 * spring在执行工程后置处理器ConfigurationClassPostProcessor时,去扫描包时会new一个ClassPathBeanDefinitionScanner
		 *
		 * 这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法
		 * 例如:AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		 * 		context.scan();
		 */
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

2.实例化工厂:DefaultListableBeanFactory

上段源码中,会隐式调用父类的构造方法,即调用父类GenericApplicationContext的构造函数。在该构造方法中创建了beanFactory----DefaultListableBeanFactory,是用来生产和获得Bean。

	public GenericApplicationContext() {
		//为ApplicationContext spring上下文对象初始化beanFactory
		//这里用的是DefaultListableBeanFactory,它是BeanFactory体系中最底层的实现,功能最多
		//该类还实现了BeanDefinitionRegistry,拥有了注册beanDefinition的能力,此功能就是该类负责的
		this.beanFactory = new DefaultListableBeanFactory();
	}

DefaultListableBeanFactory类结构图:
这里要注意DefaultListableBeanFactory实现了BeanDefinationRegistry接口,具备了注册bean定义的能力。后面关于bean定义的注册就是该类负责的。
在这里插入图片描述

3.实例化BeanDefinition读取器:AnnotatedBeanDefinitionReader

3.1 注册内置的PostProcessor 2.注册相关的BeanDefinition

我们再来看AnnotationConfigApplicationContext的无参构造方法,让我们看看Spring在初始化AnnotatedBeanDefinitionReader的时候做了什么:

	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		//把ApplicationContext对象(出入的registry)赋值给AnnotatedBeanDefinitionReader
		this.registry = registry;
		//用户处理条件注解 @Condition
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		//注册了一些spring的内置后置处理器
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}
	public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		
		//。。。。省略部分代码
	
		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		/**
		 * 为我们容器中注册了解析我们配置类的后置处理器ConfigurationClassPostProcessor
		 * Bean name :org.springframework.context.annotation.internalConfigurationAnnotationProcessor
		 * bean名称格式为:名称为“internal(内部的) + 后置处理器类名”的类的全类名
		 */
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			//在ConfigurationClassPostProcessor类中,会解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans
			//注解扫描的包,以及解析@Import注解
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		/**
		 * 为我们容器中注册了处理注解 @Autowired 的后置处理器AutowiredAnnotationBeanPostProcessor
		 * Bean name :org.springframework.context.annotation.internalAutowiredAnnotationProcessor
		 */
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		
		// 。。。。省略部分代码
		
		return beanDefs;
	}

在AnnotatedBeanDefinitionReader的构造方法中:
(1) 判断容器中是否已经存在了ConfigurationClassPostProcessor Bean
(2)如果不存在(当然这里肯定是不存在的),就通过RootBeanDefinition的构造方法获得ConfigurationClassPostProcessor的BeanDefinition,RootBeanDefinition是BeanDefinition的子类
(3)执行registerPostProcessor方法,registerPostProcessor方法内部就是注册Bean,当然这里注册其他Bean也是一样的流程。
在debug中,我们可以看到在BeanDefinitionMap中已经注册了五个对象,这些postProcessor就是spring中非常重要的内置类。比如:ConfigurationClassPostProcessor,用于解析我们配置类;AutowiredAnnotationBeanPostProcessor,用于解析@Autowire注解,这些将在后面详细分析。
在这里插入图片描述

4.创建BeanDefinition扫描器:ClassPathBeanDefinitionScanner

由于常规使用方式是不会用到AnnotationConfigApplicationContext里面的scanner的,这里的scanner 仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法。所以这里就不看 scanner是如何被实例化的了。

		 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		 context.scan();

5.注册配置类为BeanDefinition:register(annotatedClasses)

我们在回到最开始,我们分析下register(annotatedClasses)方法,其主要作用就是将配置类注册成bean定义。

	@Override
	public void register(Class<?>... componentClasses) {
		Assert.notEmpty(componentClasses, "At least one component class must be specified");
		this.reader.register(componentClasses);
	}
	public void register(Class<?>... componentClasses) {
	//配置类可以传入多个,所以要进行遍历注册,这里的componentClass就是配置类的class类型
		for (Class<?> componentClass : componentClasses) {
			registerBean(componentClass);
		}
	}
	<T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
		//beanClass:指的是存储@Configration注解注释的类,即将配置类封装成bean定义
		//把传入的标记了注解的类转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		//判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就会跳过
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(instanceSupplier);
		//解析bean的作用域,如果没有配置的话,默认是单例
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		/**
		 *  限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上是任何注解,这里没有判 断注解的有效性),
		 *  如果我们在外面,以类似这种AnnotationConfigApplicationContext annotationConfigApplicationContext =
		 *  new AnnotationConfigApplicationContext(Appconfig.class)常规方式去初始化spring,qualifiers永远都是空的,
		 *  包括上面的name和instanceSupplier都是同样的道理,但是spring提供了其他方式去注册bean,就可能会传入了
		 */
		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));
				}
			}
		}
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}

		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

		//注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法注册
		//DefaultListableBeanFactory会维护一系列的信息,比如beanDefinitionNames、beanDefinitionMap
		//beanDefinitionNames是一个List<String>,用于保存beanName
		//beanDefinitionMap.put(beanName, beanDefinition)
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

执行完此方法后可以看到,配置类的bean定义已经注册到beanDefinitionMap中。
在这里插入图片描述

6. refresh()

其实到这里,Spring还没有进行扫描,只是实例化了一个工厂,注册了一些内置的Bean和我们传进去的配置类,最重要的处理过程就是在refresh方法中完成的。

invokeBeanFactoryPostProcessors

finishBeanFactoryInitialization

扩展点:
BeanDefinition介绍:
类结构图(向上):
在这里插入图片描述
BeanMetadataElement接口:BeanDefinition元数据,返回该Bean的来源
AttributeAccessor接口:提供对BeanDefinition属性操作能力
类结构图(向下):

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值