Spring 源码解析:(三)IOC-Spring bean 的初始化过程(一)

前言

前文中已构建好源码阅读环境,也成功搭建一个demo项目,这次就开始探究Spring启动过程。

正文

Spring IoC的容器体系

IoC容器是Spring的核心模块,是抽象了对象管理、依赖关系管理的框架解决方案。Spring 提供了很多的容器,其中 BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器 必须遵从的一套原则,具体的容器实现可以增加额外的功能,比如我们常用到的ApplicationContext,其下更具体的实现如 ClassPathXmlApplicationContext 包含了解析 xml 等一系列的内容,AnnotationConfigApplicationContext 则是包含了注解解析等一系列的内容。Spring IoC 容器继承体系,需要使用哪个层次用哪个层次即可,不必使用功完全的。

BeanFactory 顶级接口方法栈如下
在这里插入图片描述
BeanFactory 容器继承体系
在这里插入图片描述
通过其接⼝设计,我们可以看到我们⼀贯使⽤的 ApplicationContext 除了继承BeanFactory的⼦接⼝,还继承了ResourceLoader、MessageSource等接⼝,因此其提供的功能也就更丰富了。

Bean生命周期关键时机点

思路是自己创建个bean,并分别在接口实现的构造器、接口方法中
断点,观察线程调用栈,分析出 Bean 对象创建和管理关键点的触发时机。

启动程序打上断点后,debug运行程序

		# debug
		AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		# 执行父类的静态代码块,获取上下文关闭事件的类名
static {
		// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
		// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
		ContextClosedEvent.class.getName();
	}

# 调用构造方法
	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		// 默认构造方法
		this();
		// 注册,参数就是传入的参数,appConfig.class
		register(componentClasses);
		// 刷新
		refresh();
	}

接下来看下,this(); 方法做了什么。


	/**
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigApplicationContext() {
		// 实例化BeanDefinition 的阅读器,用途解析BeanDefinition
		this.reader = new AnnotatedBeanDefinitionReader(this);
		// 实例化BeanDefinition 的扫描器,用途扫描需要创建的bean
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

然后调用 register(componentClasses); 方法将参数appConfig注入到BeanDefinitionMap 中。简单介绍一下
BeanDefinition, 这个类用来描述bean信息,记载了一个类的所有信息。往内深挖一下,看做了哪些操作。
debug一直往里走,看到根据参数循注册方法的调用。

	public void register(Class<?>... componentClasses) {
		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的BeanDefinition
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		// 根据原数据判断是否需要跳过下面赋值操作
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(instanceSupplier);
		// 获取原型,判断是单例还是多例
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		// 是否有其他名称
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		// 所有BeanDefinition的通用操作,给BeanDefinition属性赋值,是否懒加载,私有,依赖检查等
		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));
				}
			}
		}
		// 是否有用户自定义的BeanDefinition扩展,有进行用户自定义的扩展
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}

		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		// 这一步判断是否需要做AOP代理
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		// 注入到beanDefinitionMap中
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}


这个方法调用完成后,看到beanFactory中的beanDefinitionMap已经注入了6个beanDefinition,其中前五个是spring的RootBeanDefinition,是自己程序运行所必要的信息,后面就是根据入参appconfig而生成的beanDefinition。
在这里插入图片描述

在上个方法中,笔者讲到了对beanDefinition的一些通用操作方法,简单的挖一下这个方法


		// 所有BeanDefinition的通用操作,给BeanDefinition属性赋值,是否懒加载,关键,依赖检查等
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

// 调用processCommonDefinitionAnnotations方法
	public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
		processCommonDefinitionAnnotations(abd, abd.getMetadata());
	}

	// 根据注解类型来赋值
	static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
	// 解析元数据中是否有@Lazy的注解如果类上使用了@Lazy注解,值为true
		AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
		if (lazy != null) {
			abd.setLazyInit(lazy.getBoolean("value"));
		}
		// 只截取部分代码
	}

后话

以上笔者只截取了部分代码,剩下部分都差不多,都是解析元数据进行赋值操作。
接下来就是重头戏refresh(); 方法,这个方法是spring ioc 中最重要的方法。笔者将在下文中开始着重进行解析。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值