Spring源码(2)IOC 的初始化流程(register篇)

前言
在上一篇文章中,我们了解了IOC(基于注解)的构造器的初始化过程Spring源码(1)IOC 的初始化流程(构造器篇,基于注解)
这一篇我们开始register(componentClasses)方法的讲解

我们先回顾一下程序入口

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	//调用无参构造器
	//在本类创建 AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
	this();
	//读取componentClasses为BeanDefinition,并保存到BeanDefinitionMap中
	register(componentClasses);
	refresh();
}

这里没什么好说的,我们直接进入register方法

//AnnotationConfigApplicationContext
public void register(Class<?>... componentClasses) {
	Assert.notEmpty(componentClasses, "At least one component class must be specified");
	this.reader.register(componentClasses);
}

//AnnotatedBeanDefinitionReader
public void register(Class<?>... componentClasses) {
	for (Class<?> componentClass : componentClasses) {
		registerBean(componentClass);
	}
}
public void register(Class<?>... componentClasses) {
	for (Class<?> componentClass : componentClasses) {
		registerBean(componentClass);
	}
}

public void registerBean(Class<?> beanClass) {
	doRegisterBean(beanClass, null, null, null, null);
}

这里使用AnnotatedBeanDefinitionReader进行注册,代码很简单我们直接来到doRegisterBean(这里说一点,其实spring真正进行操作的方法都是以do开头的,没do开头一般只做一些准备操作)方法进行讲解

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
		//将beanClass解析为BeanDefinition对象
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		//conditionEvaluator是在AnotatedBeanDefinitionReader类初始化的时候初始化的,
		//ConditionEvaluator这个类主要用于完成条件注解@Conditional的解析和判断。
		//@Conditional 是Spring 4框架的新特性。此注解使得只有在特定条件满足时才启用一些配置。
		//ConditionEvaluator的shouldSkip就是用于判断@Conditional下的而配置是否被启用。
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}
		//supplier a callback for creating an instance of the bean
		//这里设置的supplier,会在doCreateBean 的时候使用它来创建实例
		abd.setInstanceSupplier(supplier);
		//获取作用域
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		//设置作用域
		abd.setScope(scopeMetadata.getScopeName());
		//获取beanName,如果传入的beanName为空,则调用beanName生成策略
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		//注解处理
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

		//下面这一段代码是针对 @Qualifier注解的,一般情况下,
		// @Autowired是根据类型进行自动装配的。
		// 如果当Spring上下文中存在不止一个该类型的bean时,就会抛出BeanCreationException异常。
		// @Qualifier可以配置自动依赖注入装配的限定条件,
		// @Qualifier 可以直接指定注入 Bean 的名称,简单来说,
		// @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。
		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));
				}
			}
		}
		//可以BeanDefinitionCustomizer的回调去修改BeanDefinition的信息
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}
		//这里面定义了beanDefinition的名称和beanDefinition实例还有别名
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		//在为创建该类的时候使用什么代理模式去创建,主要应用在为singleton注入其他作用域的对象的时候
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//将BeanDefinition注册到BeanDefinitionMap中
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

这里主要做了一下几步

  1. 将beanClass解析为BeanDefinition对象
  2. 生成BeanDefinition name
  3. 将BeanDefinition name 和BeanDefinition 以key value的方式保存到BeanDefinitionMap中

下面我们将会对doRegisterBean中的一些比较重要的方法进行讲解

  1. ScopeMetadata scopeMetadata =
    this.scopeMetadataResolver.resolveScopeMetadata(abd);
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
	ScopeMetadata metadata = new ScopeMetadata();
	//只有AnnotatedBeanDefinition的子类才支持解析注解元数据,不是的话周就直接返回默认ScopeMetadata
	if (definition instanceof AnnotatedBeanDefinition) {
		AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
				annDef.getMetadata(), this.scopeAnnotationType);
		//如果不为空的话就获取并设置注解相关信息
		if (attributes != null) {
			//获取scope注解的value值并保存
			metadata.setScopeName(attributes.getString("value"));
			//设置proxyMode 
			ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
			if (proxyMode == ScopedProxyMode.DEFAULT) {
				proxyMode = this.defaultProxyMode;
			}
			metadata.setScopedProxyMode(proxyMode);
		}
	}
	return metadata;
}


//ScopedProxyMode 是一个枚举类
public enum ScopedProxyMode {
	//默认为INTERFACES
	DEFAULT,
	//关闭ScopedProxy
	NO,
	//CGlib
	INTERFACES,
	//JDK动态代理
	TARGET_CLASS

}

我相信你们对于ScopedProxyMode肯定有很多疑问,我们这里先简单地理解(后面我们会着重的讲)为,当我初始化时向scope 为singleton(我们把它称为singletonBean)的bean中注入一个socpe session(我们把它称为sessionBean)的bean,此时sessionBean时无法创建的,所以此时就需要给它创建一个代理对象。

  1. String beanName = (name != null ? name :
    this.beanNameGenerator.generateBeanName(abd, this.registry));
//如果入参的name为null的话这调用方法generateBeanName生成beanName
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
	if (definition instanceof AnnotatedBeanDefinition) {
		//获去@Component的value值
		String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
		if (StringUtils.hasText(beanName)) {
			// Explicit bean name found.
			return beanName;
		}
	}
	// 使用默认策略生成beanName
	return buildDefaultBeanName(definition, registry);
}


protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
	//获取元数据
	AnnotationMetadata amd = annotatedDef.getMetadata();
	//获取注解类型
	Set<String> types = amd.getAnnotationTypes();
	String beanName = null;
	for (String type : types) {
		//保存了注解里的所有数据
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
		if (attributes != null) {
			//保存到缓存,这里保存了type为key,set为value,set里面保存在type里多有注解信息
			Set<String> metaTypes = this.metaAnnotationTypesCache.computeIfAbsent(type, key -> {
				Set<String> result = amd.getMetaAnnotationTypes(key);
				return (result.isEmpty() ? Collections.emptySet() : result);
			});
			//判断是否是component或者包含component
			if (isStereotypeWithNameValue(type, metaTypes, attributes)) {
				//获取value的值
				Object value = attributes.get("value");
				if (value instanceof String) {
					String strVal = (String) value;
					if (StringUtils.hasLength(strVal)) {
						//不明白这里判空的意义在哪里
						if (beanName != null && !strVal.equals(beanName)) {
							throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
									"component names: '" + beanName + "' versus '" + strVal + "'");
						}
						beanName = strVal;
					}
				}
			}
		}
	}
	return beanName;
}


protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
	return buildDefaultBeanName(definition);
}

protected String buildDefaultBeanName(BeanDefinition definition) {
	//获取className
	String beanClassName = definition.getBeanClassName();
	Assert.state(beanClassName != null, "No bean class name set");
	//获取简单类名,意思就是不包含包名
	String shortClassName = ClassUtils.getShortName(beanClassName);
	//首字母小写
	return Introspector.decapitalize(shortClassName);
}

这里主要做了一下操作:
判断是否有Component注解,有的话,获取value的值,否则,使用默认beanName生成策略,也就是首字母小写的类名

  1. AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
		processCommonDefinitionAnnotations(abd, abd.getMetadata());
	}

	static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
		//获取并设置bean上注解(Lazy)的信息
		AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
		if (lazy != null) {
			abd.setLazyInit(lazy.getBoolean("value"));
		}
		else if (abd.getMetadata() != metadata) {
			lazy = attributesFor(abd.getMetadata(), Lazy.class);
			if (lazy != null) {
				abd.setLazyInit(lazy.getBoolean("value"));
			}
		}
		//获取并设置bean上注解(Primary)的信息
		if (metadata.isAnnotated(Primary.class.getName())) {
			abd.setPrimary(true);
		}
		//获取并设置bean上注解(DependsOn)的信息
		AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
		if (dependsOn != null) {
			abd.setDependsOn(dependsOn.getStringArray("value"));
		}
		//获取并设置bean上注解(Role)的信息
		AnnotationAttributes role = attributesFor(metadata, Role.class);
		if (role != null) {
			abd.setRole(role.getNumber("value").intValue());
		}
		//获取并设置bean上注解(Description)的信息
		AnnotationAttributes description = attributesFor(metadata, Description.class);
		if (description != null) {
			abd.setDescription(description.getString("value"));
		}
	}
  1. definitionHolder =
    AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,
    definitionHolder, this.registry);
static BeanDefinitionHolder applyScopedProxyMode(
		ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

	ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
	//如果为NO,则不做处理,直接返回
	if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
		return definition;
	}
	//校验scopedProxyMode是否为ScopedProxyMode.TARGET_CLASS,(TARGET_CLASS:CGLIB)
	boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
	//创建代理BeanDefintion,并返回
	return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}

public static BeanDefinitionHolder createScopedProxy(
	BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {

	return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
	}

public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
			BeanDefinitionRegistry registry, boolean proxyTargetClass) {
		//获取原本的beanDefinition Name,beanDefinition实例,targetBeanName = "scopedTarget."+originalBeanName
		String originalBeanName = definition.getBeanName();
		BeanDefinition targetDefinition = definition.getBeanDefinition();
		String targetBeanName = getTargetBeanName(originalBeanName);

		//创建一个代理beanDefinition
		RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
		//设置代理的BeanDefinitionHolder
		proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
		//设置代理的BeanDefinition
		proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
		//资源
		proxyDefinition.setSource(definition.getSource());
		
		//角色
		proxyDefinition.setRole(targetDefinition.getRole());		
		//配置属性值,后面再填充属性的时候你就会明白
		proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
		//ScopedProxyMode 是否为TARGET_CLASS
		if (proxyTargetClass) {
			targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
		}
		else {
			proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
		}

		// Copy autowire settings from original bean definition.
		//设置是否支持候选bean,后面填充属性会讲解
		proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
	//设置Primary	
		proxyDefinition.setPrimary(targetDefinition.isPrimary());
		if (targetDefinition instanceof AbstractBeanDefinition) {
			proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
		}

		// The target bean should be ignored in favor of the scoped proxy.
		//设置被代理的Bean
		targetDefinition.setAutowireCandidate(false);
		targetDefinition.setPrimary(false);

		// 将被代理的bean注册到BeanDefinitionMap中
		registry.registerBeanDefinition(targetBeanName, targetDefinition);

		// 返回代理的BeanDefinitionHolder
		return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
	}

到这里,register方法的基本流程就已经讲完了
我们一起来看看做了什么事情

  1. 将beanClass解析为BeanDefinition对象
  2. 判断是否有condition注解,是否满足condition的条件
  3. 生成BeanDefinition name
  4. 对Lazy,Primary,DependOn等注解的设置
  5. 可以BeanDefinitionCustomizer对BeanDefiniton进行回调处理
  6. 处理并返回BeanDefinitionHolder
  7. 将BeanDefinition name 和BeanDefinition 以key
    value的方式保存到BeanDefinitionMap中
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值