【Spring源代码阅读之六】处理配置类的@Import、@Bean、父接口方法的@Bean并解析,同时解析@ImportResource

导图

在这里插入图片描述

开始处理

ConfigurationClassParser#processImports

/**
 * 处理@Import注解
 */
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
		Collection<SourceClass> importCandidates, boolean checkForCircularImports) {

	/**
	 * 如果没有需要处理的@Import注解则不解析
	 */
	if (importCandidates.isEmpty()) {
		return;
	}

	if (checkForCircularImports && isChainedImportOnStack(configClass)) {
		this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
	}
	else {
		/**
		 * 将需要处理的类压入到处理栈中
		 */
		this.importStack.push(configClass);
		try {
			/**
			 * 遍历处理
			 * 注意:@Import注解可以传入三种类型的类
			 * 		1、实现了ImportSelector接口的类class
			 * 		2、实现了ImportBeanDefinitionRegistrar接口的类class
			 * 		3、未实现以上两种接口的类class
			 */
			for (SourceClass candidate : importCandidates) {
				/**
				 * 处理实现了ImportSelector接口的类
				 */
				if (candidate.isAssignable(ImportSelector.class)) {
					// Candidate class is an ImportSelector -> delegate to it to determine imports
					/**
					 * 获取类的Class并通过反射创建实例
					 */
					Class<?> candidateClass = candidate.loadClass();
					ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);

					/**
					 * 如果实例实现了一些Spring的接口,则利用接口方法为其注入依赖
					 */
					ParserStrategyUtils.invokeAwareMethods(
							selector, this.environment, this.resourceLoader, this.registry);

					/**
					 * 如果实例实现了DeferredImportSelector接口,实例并不会立即进行解析,放入懒加载集合中稍后处理
					 */
					if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
						this.deferredImportSelectors.add(
								new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
					}
					/**
					 * 相反则会立即解析执行ImportSelector接口的selectImports方法
					 * 该方法会返回需要加载到容器中的类全限定名,数组类型,可加载多个
					 * 通过这些类名加载类并转化为SourceClass
					 * 注意:这里这个实现了ImportSelector接口的实例并不会加载到容器中
					 * 注意:Spring高明的是,这里使用了递归处理,即这些类会被当做@Import注解中类的处理逻辑
					 * 		进行处理,这样的好处是,我返回的全限定名的类也可以实现ImportSelector接口和
					 * 		ImportBeanDefinitionRegistrar接口从而发挥相应的作用,但是,如果只是一个普通的类,则
					 * 		可以利用@Import处理普通类的处理逻辑进行处理,避免代码冗余
					 */
					else {
						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
						processImports(configClass, currentSourceClass, importSourceClasses, false);
					}
				}
				/**
				 * 处理实现了ImportSelector接口的类
				 * 这里的逻辑比较简单,如果实例实现了ImportBeanDefinitionRegistrar接口
				 * 首先像上面一样,通过反射创建实例,为其注入一些Aware接口的依赖
				 * 然后不同的是,这里并没有处理这个实例,而是放入了@Import注解所在的配置类构成的
				 * SourceClass实例中关于实现ImportBeanDefinitionRegistrar实例的一个Map集合中
				 */
				else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
					// Candidate class is an ImportBeanDefinitionRegistrar ->
					// delegate to it to register additional bean definitions
					Class<?> candidateClass = candidate.loadClass();
					ImportBeanDefinitionRegistrar registrar =
							BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
					ParserStrategyUtils.invokeAwareMethods(
							registrar, this.environment, this.resourceLoader, this.registry);
					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
				}
				/**
				 * 第三种类型,未实现以上两种接口的类
				 * 将其压入普通类处理栈中,然后这个类按照处理配置类的逻辑进行处理
				 * 具体请看processConfigurationClass方法。其最终会放入一个集合中,并不会注册进容器中
				 */
				else {
					// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
					// process it as an @Configuration class
					this.importStack.registerImport(
							currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
					processConfigurationClass(candidate.asConfigClass(configClass));
				}
			}
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(
					"Failed to process import candidates for configuration class [" +
					configClass.getMetadata().getClassName() + "]", ex);
		}
		finally {
			this.importStack.pop();
		}
	}
}

ConfigurationClassParser#retrieveBeanMethodMetadata

/**
 * 解析类中含有@Bean注解的方法
 */
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
	/**
	 * 获取含有@Bean注解的方法的元信息
	 */
	AnnotationMetadata original = sourceClass.getMetadata();
	Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
	/**
	 * 如果含有@Bean注解的方法超过两个,并且是标准注解信息,则Spring会使用ASM技术
	 * Spring使用了JAVA的反射机制获取的Class,但是反射不能保证方法的声明顺序,也就是它所返回的方法顺序
	 * 并不一定是代码从上到下编写的顺序,有可能类中的最下面的一个方法在beanMethods集合中是第一个
	 * Spring为保证方法的声明顺序,使用ASM技术读取作比较
	 * 注意:这里只有ASM获取的方法比反射获取的方法多或者相等才会比较
	 */
	if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
		// Try reading the class file via ASM for deterministic declaration order...
		// Unfortunately, the JVM's standard reflection returns methods in arbitrary
		// order, even between different runs of the same application on the same JVM.
		try {
			/**
			 * 利用ASM技术返回类的元信息,并获取含有@Bean注解的方法元信息
			 */
			AnnotationMetadata asm =
					this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
			Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
			/**
			 * 这里重新创建了一个LinkedHashSet集合保证放入的顺序,遍历ASM方法名与java反射方法名一致
			 * 则可以放入集合中并赋值给局部变量用于返回
			 */
			if (asmMethods.size() >= beanMethods.size()) {
				Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
				for (MethodMetadata asmMethod : asmMethods) {
					for (MethodMetadata beanMethod : beanMethods) {
						if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
							selectedMethods.add(beanMethod);
							break;
						}
					}
				}
				if (selectedMethods.size() == beanMethods.size()) {
					// All reflection-detected methods found in ASM method set -> proceed
					beanMethods = selectedMethods;
				}
			}
		}
		catch (IOException ex) {
			logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
			// No worries, let's continue with the reflection metadata we started with...
		}
	}
	return beanMethods;
}

ConfigurationClassParser#processInterfaces

/**
 * 获取接口上含有@Bean注解的方法
 */
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
	/**
	 * 获取父级接口,遍历
	 */
	for (SourceClass ifc : sourceClass.getInterfaces()) {
		/**
		 * 获取接口中含有@Bean注解的方法元信息,然后遍历
		 */
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
		for (MethodMetadata methodMetadata : beanMethods) {
			/**
			 * 只要此方法不是抽象类型的,则可以放入集合中待后续处理
			 */
			if (!methodMetadata.isAbstract()) {
				// A default method or other concrete method on a Java 8+ interface...
				configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
			}
		}
		/**
		 * 这里使用了递归,用来处理父级接口的父接口
		 */
		processInterfaces(configClass, ifc);
	}
}

以下是解析

ConfigurationClassBeanDefinitionReader#loadBeanDefinitions

/**
 * 对加载的配置类中待处理的配置进行解析
 */
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
	/**
	 * 构建条件解析对象
	 */
	TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
	/**
	 * 遍历配置类将待处理的配置处理了
	 */
	for (ConfigurationClass configClass : configurationModel) {
		loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
	}
}

loadBeanDefinitionsForConfigurationClass

/**
 * 处理配置类中待加入容器中的配置
 * 其中包括:
 * 		1、@Import注解中的普通类和实现ImportSelector接口方法返回的类名(通过这些类名加载的类)
 * 		2、@Import注解中实现了ImportBeanDefinitionRegistrar接口的类
 * 		3、@ImportResource注解
 * 		4、含有@Bean注解的方法
 */
private void loadBeanDefinitionsForConfigurationClass(
		ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

	/**
	 * 判断配置类是否符合加载条件,如果返回true的话就证明不符合加载条件
	 * 这时需要将环境中关于此配置的一些信息删除掉
	 */
	if (trackedConditionEvaluator.shouldSkip(configClass)) {
		String beanName = configClass.getBeanName();
		if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
			this.registry.removeBeanDefinition(beanName);
		}
		this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
		return;
	}

	/**
	 * 如果此类是被其他类导入的,则将其注册进容器中
	 */
	if (configClass.isImported()) {
		registerBeanDefinitionForImportedConfigurationClass(configClass);
	}

	/**
	 * 解析@Bean方法,将返回的对象注册进容器中
	 */
	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		loadBeanDefinitionsForBeanMethod(beanMethod);
	}

	/**
	 * 解析@ImportResource注解,就是将XML配置文件中的Bean加载到容器中(暂不研究)
	 */
	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

	/**
	 * 解析@Import注解中实现了ImportBeanDefinitionRegistrar接口的类
	 */
	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

registerBeanDefinitionForImportedConfigurationClass

/**
 * 将被导入的配置类转化成BeanDefinition注册进容器中
 */
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
	/**
	 * 获取配置类的元信息并通过构造函数创建一个BeanDefinition
	 */
	AnnotationMetadata metadata = configClass.getMetadata();
	AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

	/**
	 * 设置动态代理模型,关于web的
	 */
	ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
	configBeanDef.setScope(scopeMetadata.getScopeName());
	/**
	 * 通过BeanName生成器创建BeanName
	 */
	String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
	/**
	 * 解析配置类的一些其它注解
	 */
	AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

	/**
	 * 构建Holder封装对象
	 */
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
	/**
	 * 关于动态代理模型
	 */
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	/**
	 * 将配置类的BeanDefinition注册进容器中
	 */
	this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
	/**
	 * 给自己设置BeanName
	 */
	configClass.setBeanName(configBeanName);

	if (logger.isDebugEnabled()) {
		logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
	}
}

loadBeanDefinitionsForBeanMethod

/**
 * 处理配置类中@Bean注解的方法
 * @param beanMethod
 */
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
	/**
	 * 获得方法所在类的类信息
	 */
	ConfigurationClass configClass = beanMethod.getConfigurationClass();
	/**
	 * 获得方法的元信息
	 */
	MethodMetadata metadata = beanMethod.getMetadata();
	/**
	 * 获得方法名
	 */
	String methodName = metadata.getMethodName();

	// Do we need to mark the bean as skipped by its condition?
	/**
	 * 此方法是否需要跳过解析
	 */
	if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
		configClass.skippedBeanMethods.add(methodName);
		return;
	}
	if (configClass.skippedBeanMethods.contains(methodName)) {
		return;
	}

	/**
	 * 获得@Bean注解中的属性
	 */
	AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
	Assert.state(bean != null, "No @Bean annotation attributes");

	// Consider name and any aliases
	/**
	 * 获得@Bean注解中指定方法返回对象的BeanName
	 * 如果没有设置则默认使用方法名
	 * 如果设置了则使用第一个名称,其它名称作为别名,因为@Bean注解中name属性为数组
	 */
	List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
	String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

	// Register aliases even when overridden
	for (String alias : names) {
		this.registry.registerAlias(beanName, alias);
	}

	// Has this effectively been overridden before (e.g. via XML)?
	/**
	 * 判断容器中与beanName相同的BeanDefinition是否可以被覆盖
	 */
	if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
		/**
		 * 如果@Bean所在方法配置的beanName与配置类的BeanName相同,则抛异常
		 */
		if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
			throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
					beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
					"' clashes with bean name for containing configuration class; please make those names unique!");
		}
		return;
	}

	/**
	 * 通过@Bean所在方法元信息和类信息构建BeanDefinition
	 */
	ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
	/**
	 * 设置BeanDefinition的来源
	 */
	beanDef.setResource(configClass.getResource());
	/**
	 * 设置BeanDefinition的提取源,即所代表的对象从哪里提取,取决于配置机制
	 * 默认使用PassThroughSourceExtractor这个类,机制是按原样返回,即从方法中提取
	 */
	beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

	/**
	 * 如果方法是static静态类型,将其置为静态方法调用
	 * 实际就是向BeanDefinition中设置工厂方法名称,即产生对象需要调用的方法
	 */
	if (metadata.isStatic()) {
		// static @Bean method
		beanDef.setBeanClassName(configClass.getMetadata().getClassName());
		beanDef.setFactoryMethodName(methodName);
	}
	/**
	 * 如果不是静态类型,将其置为实例调用
	 */
	else {
		// instance @Bean method
		beanDef.setFactoryBeanName(configClass.getBeanName());
		beanDef.setUniqueFactoryMethodName(methodName);
	}
	/**
	 * 设置由方法提取的实例为属性自动注入的方式,默认为构造方法
	 */
	beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
	/**
	 * 是否跳过属性检查
	 */
	beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

	/**
	 * 提取方法上的其它注解
	 */
	AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

	/**
	 * 设置由方法提取的实例是否会根据类型或者名称为属性自动注入,默认不会,除非显示设置
	 */
	Autowire autowire = bean.getEnum("autowire");
	if (autowire.isAutowire()) {
		beanDef.setAutowireMode(autowire.value());
	}

	/**
	 * 指定由方法提取的实例的初始化方法名
	 */
	String initMethodName = bean.getString("initMethod");
	if (StringUtils.hasText(initMethodName)) {
		beanDef.setInitMethodName(initMethodName);
	}

	/**
	 * 指定由方法提取的实例的销毁方法名
	 */
	String destroyMethodName = bean.getString("destroyMethod");
	beanDef.setDestroyMethodName(destroyMethodName);

	// Consider scoping
	/**
	 * 设置动态代理模型的初始值
	 */
	ScopedProxyMode proxyMode = ScopedProxyMode.NO;
	/**
	 * 获得方法上的@Scope注解
	 */
	AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
	/**
	 * 存在@Scope注解时进行相关的设置
	 */
	if (attributes != null) {
		/**
		 * 设置作用域
		 */
		beanDef.setScope(attributes.getString("value"));
		/**
		 * 设置动态代理模型,如果是使用默认的话则置为初始化值
		 */
		proxyMode = attributes.getEnum("proxyMode");
		if (proxyMode == ScopedProxyMode.DEFAULT) {
			proxyMode = ScopedProxyMode.NO;
		}
	}

	// Replace the original bean definition with the target one, if necessary
	BeanDefinition beanDefToRegister = beanDef;
	/**
	 * 如果需要动态代理的话,则将原始的BeanDefinition替换为动态代理的BeanDefinition
	 */
	if (proxyMode != ScopedProxyMode.NO) {
		BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
				new BeanDefinitionHolder(beanDef, beanName), this.registry,
				proxyMode == ScopedProxyMode.TARGET_CLASS);
		beanDefToRegister = new ConfigurationClassBeanDefinition(
				(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
	}

	if (logger.isDebugEnabled()) {
		logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
				configClass.getMetadata().getClassName(), beanName));
	}
	/**
	 * 将其注册进容器中
	 */
	this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
isOverriddenByExistingDefinition
/**
 * 如果容器中存在与beanName相同的BeanDefinition是否可以被覆盖
 * 返回false则是没有与beanName相同的BeanDefinition或者可以被覆盖
 * 返回true则不能覆盖
 */
protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
	/**
	 * 根据beanName判断容器中是否已经存在相应的BeanDefinition,不存在则返回false可以注册到容器中
	 */
	if (!this.registry.containsBeanDefinition(beanName)) {
		return false;
	}
	/**
	 * 获取容器中BeanName对应的BeanDefinition
	 */
	BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);

	// Is the existing bean definition one that was created from a configuration class?
	// -> allow the current bean method to override, since both are at second-pass level.
	// However, if the bean method is an overloaded case on the same configuration class,
	// preserve the existing bean definition.
	/**
	 * 如果容器中的BeanDefinition是一个ConfigurationClassBeanDefinition
	 * 		ConfigurationClassBeanDefinition是由@Bean注解方法返回对象封装的
	 * 如果配置类的类名和@Bean方法所在类的类名相同,则返回true,这时发生了重载,不解析@Bean所在的方法
	 * 如果类名不相同,则解析@Bean所在的方法,覆盖容器中存在的
	 */
	if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
		ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
		return ccbd.getMetadata().getClassName().equals(
				beanMethod.getConfigurationClass().getMetadata().getClassName());
	}

	// A bean definition resulting from a component scan can be silently overridden
	// by an @Bean method, as of 4.2...
	/**
	 * 如果容器中存在的BeanDefinition是通过扫描注册的,则@Bean方法的BeanDefinition会覆盖容器中存在的
	 */
	if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
		return false;
	}

	// Has the existing bean definition bean marked as a framework-generated bean?
	// -> allow the current bean method to override it, since it is application-level
	/**
	 * 如果容器中存在的BeanDefinition是应用程序级别的,则@Bean方法的BeanDefinition可以覆盖容器中的
	 */
	if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
		return false;
	}

	// At this point, it's a top-level override (probably XML), just having been parsed
	// before configuration class processing kicks in...
	/**
	 * 通过以上判断,仍然不能确定容器中的BeanDefinition是否能被覆盖
	 * 如果当前注册器实现了DefaultListableBeanFactory(肯定实现了)并且DefaultListableBeanFactory不允许覆盖
	 * BeanDefinition,此时就会抛异常,因为不允许覆盖的情况下而应用程序中出现了两个相同的BeanDefinition
	 * 如果允许覆盖,则返回true,注意此时也是不会解析@Bean所在方法的,这里的允许覆盖是允许其它来源的
	 * BeanDefinition可以覆盖,比如XML
	 */
	if (this.registry instanceof DefaultListableBeanFactory &&
			!((DefaultListableBeanFactory) this.registry).isAllowBeanDefinitionOverriding()) {
		throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
				beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
	}
	if (logger.isInfoEnabled()) {
		logger.info(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
				"already exists. This top-level bean definition is considered as an override.",
				beanMethod, beanName));
	}
	return true;
}

loadBeanDefinitionsFromRegistrars

/**
 * 执行@Import注解中实现了ImportBeanDefinitionRegistrar接口的类,其实就是执行实现了接口的方法
 * 这里使用了lambda表达式遍历
 */
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
	registrars.forEach((registrar, metadata) ->
			registrar.registerBeanDefinitions(metadata, this.registry));
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值