栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring源码系列(二)——注册配置类

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring源码系列(二)——注册配置类

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
    // 这里由于它有父类构造方法,故而先调用父类的构造方法,然后才会调用自己的构造方法
    this();
    register(annotatedClasses);
    refresh();
}

在第一篇文章中,研究了this()中的源码,下面要来探究register(annotatedClasses);这行代码的秘密了。

一、注册配置类
register(annotatedClasses);

这个标题,完全是翻译上面这行代码,下面就慢慢往下分析吧。先贴一下配置类AppConfig的代码,简单哦。

@Configuration
@ComponentScan("com.scorpios")
public class AppConfig {
}

AnnotationConfigApplicationContext类中的register()方法,发现这个方法可以传多个配置类。

public void register(Class... annotatedClasses) {
    // 这个reader读取器,就是在上面创建容器时无参构造器中创建的reader!
    this.reader.register(annotatedClasses);
}

// 如果传入的是多个配置类,则要进行循环
public void register(Class... annotatedClasses) {
    for (Class annotatedClass : annotatedClasses) {
        // 把配置类转化为BeanDefinition放入到beanDefinitionMap中
        registerBean(annotatedClass);
    }
}

二、注册Bean

下面来研究下AnnotatedBeanDefinitionReader中的registerBean(annotatedClass);这个方法。

// 这个方法就是将一个类转化为一个BeanDefinition,给BeanDefinition里面的属性确定值
 void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
		@Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

	
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

	// 判断这个类是否需要跳过解析,通过代码可以知道spring判断是否跳过解析,主要判断类有没有加特定注解
	if (this.conditionevaluator.shouldSkip(abd.getmetadata())) {
		return;
	}

	// 不知道
	abd.setInstanceSupplier(instanceSupplier);
	// 得到类的作用域
	Scopemetadata scopemetadata = this.scopemetadataResolver.resolveScopemetadata(abd);
	// 把类的作用域添加到数据结构结构中
	abd.setScope(scopemetadata.getScopeName());
	// 通过beanNameGenerator生成类的名字,
    // 这地方是根据ClassName来截取的类名:com.scorpios.app.AppConfig
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));


	// 此处是处理类当中的通用注解,分析源码可以知道主要处理Lazy、Primary、DependsOn、Role、Description等注解
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

	
    // 此参数是方法传入的,永远为空,如何给一个Bean传入Primary属性呢?两个方式,一个是加@Primary注解,一个就是往qualifiers中添加Primary
	if (qualifiers != null) {
		for (Class qualifier : qualifiers) {
			// 如果配置了@Primary注解,如果加了则作为首选
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			} else if (Lazy.class == qualifier) {// 懒加载
				abd.setLazyInit(true);
			} else {
				// 如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一个根据名字自动装配的限定符
				abd.addQualifier(new AutowireCandidateQualifier(qualifier));
			}
		}
	}
    // 忽略
	for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
		customizer.customize(abd);
	}

	// 这个BeanDefinitionHolder也是一个数据结构
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	// ScopedProxyMode 这个知识点比较复杂,需要结合web去理解
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopemetadata, definitionHolder, this.registry);
    
	
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
三、小结

这个方法执行完,beanDefinitionMap中共有7个BeanDefinition对象,分别是之前创建读取器Reader时,Spring容器自己添加的6个,加上这个register(annotatedClasses);添加的一个。

见下图:



这里再强调一个概念,Spring容器需要将Class类转化成BeanDefinition,最后Spring容器是根据这个BeanDefinition来创建实例的。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/340221.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号