Spring源码解析(六):bean定义后置处理器ConfigurationClassPostProcessor

news2024/11/18 9:47:57

Spring源码系列文章

Spring源码解析(一):环境搭建

Spring源码解析(二):bean容器的创建、默认后置处理器、扫描包路径bean

Spring源码解析(三):bean容器的刷新

Spring源码解析(四):单例bean的创建流程

Spring源码解析(五):循环依赖

Spring源码解析(六):bean定义后置处理器ConfigurationClassPostProcessor


目录

  • 一、ConfigurationClassPostProcessor简介
  • 二、postProcessBeanDefinitionRegistry()(添加bean定义)
    • 1、checkConfigurationClassCandidate筛选配置类
    • 2、parser.parse(candidates) 解析配置类
      • 2.1、处理@Component注解的内部类
      • 2.2、处理@PropertySource注解
      • 2.3、处理@ComponentScan @ComponentScans注解
      • 2.4、处理@Import 注解
      • 2.5、处理@ImportResource注解
      • 2.6、处理 @Bean修饰的方法
    • 3、this.reader.loadBeanDefinitions(configClasses) 加载bean定义
  • 三、postProcessBeanFactory()(cglib代理配置类)
    • 解决问题及示例
    • 1、postProcessBeanFactory方法内容
    • 2、enhanceConfigurationClasses 方法用于增强配置类
    • 3、总结

一、ConfigurationClassPostProcessor简介

类图如下:

在这里插入图片描述

  • ConfigurationClassPostProcessor是BeanDefinitionRegistryPostProcessor(bean定义后置处理器
    • BeanDefinitionRegistryPostProcessor父类是BeanFactoryPostProcessor(bean工厂后置处理器
  • 根本作用就是解析注解给bean容器添加bean定义
    • @Configuration,@Import,@ComponentScan,@Bean等注解
  • 因为有很多后置处理器,通过实现Ordered接口排序执行

后置处理器重写的两个重要方法

  • postProcessBeanFactory():BeanFactoryPostProcessor接口方法
  • postProcessBeanDefinitionRegistry():BeanDefinitionRegistryPostProcessor接口方法
  • 之前文章Spring源码解析(三):bean容器的刷新已经讲过,调用过程主要是在 Spring容器刷新的过程中,其中postProcessBeanDefinitionRegistry方法先于postProcessBeanFactory方法被调用
// 添加bean的定义
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
// 完成对@Bean方法的代理 (目的是为了在配置类中多次调用@Bean方法返回的是同一个结果)
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

二、postProcessBeanDefinitionRegistry()(添加bean定义)

  • 进入ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

在这里插入图片描述

  • 核心方法在processConfigBeanDefinitions(),执行配置bean定义
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
	// 获取已经解析的BeanName
	String[] candidateNames = registry.getBeanDefinitionNames();
	// 遍历BeanName
	for (String beanName : candidateNames) {
		// 获取BeanDefinition
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		// 如果bean被解析过则设置属性CONFIGURATION_CLASS_ATTRIBUTE值
		// 为了防止重复解析配置类
		if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
			}
		}
		// 1.筛选配置类
		else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
			// 添加到配置类集合中
			configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
		}
	}

	// 如果未找到@Configuration类,请立即返回
	if (configCandidates.isEmpty()) {
		return;
	}

	// 对configCandidates 进行 排序,按照@Order 配置的值进行排序
	configCandidates.sort((bd1, bd2) -> {
		int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
		int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
		return Integer.compare(i1, i2);
	});

	// 检测是否有自定义bean名称生成器
	// 判断如果是registry是SingletonBeanRegistry类型,则从中获取 beanName 生成器(BeanNameGenerator )
	// 实际上这里是 register 类型是 DefaultListableBeanFactory。是SingletonBeanRegistry的子类
	SingletonBeanRegistry sbr = null;
	if (registry instanceof SingletonBeanRegistry) {
		sbr = (SingletonBeanRegistry) registry;
		if (!this.localBeanNameGeneratorSet) {
			BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
					AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
			if (generator != null) {
				this.componentScanBeanNameGenerator = generator;
				this.importBeanNameGenerator = generator;
			}
		}
	}

	// 如果环境变量为空则指定一个标准环境
	if (this.environment == null) {
		this.environment = new StandardEnvironment();
	}

	// 下面开始解析每一个配置类
	// 准备配置类的解析类ConfigurationClassParser
	ConfigurationClassParser parser = new ConfigurationClassParser(
			this.metadataReaderFactory, this.problemReporter, this.environment,
			this.resourceLoader, this.componentScanBeanNameGenerator, registry);

	// 用来保存尚未解析的配置类
	Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
	// 用来保存已经解析的配置类
	Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());

	do {
		StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
		// 2.解析配置类
		parser.parse(candidates);
		// 3.这里的校验规则是如果是被@Configuration修饰且proxyBeanMethods属性为true,则类不能为final
		// 如果@Bean修饰的方法,则必须是可覆盖的
		// 因为@Configuration(proxyBeanMethods = true) 是需要cglib代理的,所以不能为终态, @Bean所修饰的方法也有一套约束规则
		// 是否需要代理是根据 类或方法上的 @Scope 注解指定的,默认都是不代理
		parser.validate();

		// 保存这次解析出的配置类。此时这些ConfigurationClass 中保存了解析出来的各种属性值,等待最后构建 BeanDefinition
		Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
		// 去除已经解析过的配置类
		configClasses.removeAll(alreadyParsed);

		// 构造一个bean定义读取器
		if (this.reader == null) {
			this.reader = new ConfigurationClassBeanDefinitionReader(
					registry, this.sourceExtractor, this.resourceLoader, this.environment,
					this.importBeanNameGenerator, parser.getImportRegistry());
		}
		// 4.读取ConfigurationClass获取衍生bean定义并注册到容器
		this.reader.loadBeanDefinitions(configClasses);
		// 添加到以及解析的集合
		alreadyParsed.addAll(configClasses);
		processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
		// 清空候选配置类定义列表,如果没有新增bean,则会跳出do while循环
		candidates.clear();
		// 如果容器中bean定义有新增
		// 也就是解析完这一批bean后,可能会新增一批bean,那么为啥会有新增的呢?
		// 例如解析该@Configuration,里面可能有@Bean,这个就是新增的@Bean
		// 类似于一个递归去解析,一点点扩大范围
		if (registry.getBeanDefinitionCount() > candidateNames.length) {
			String[] newCandidateNames = registry.getBeanDefinitionNames();
			Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
			Set<String> alreadyParsedClasses = new HashSet<>();
			for (ConfigurationClass configurationClass : alreadyParsed) {
				alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
			}
			for (String candidateName : newCandidateNames) {
				// 筛选是否为旧的配置类
				if (!oldCandidateNames.contains(candidateName)) {
					BeanDefinition bd = registry.getBeanDefinition(candidateName);
					// 筛选是否为标注了@Configuration的配置类 && 是否为已经解析完成的配置类
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
							!alreadyParsedClasses.contains(bd.getBeanClassName())) {
						candidates.add(new BeanDefinitionHolder(bd, candidateName));
					}
				}
			}
			// 替换一下,继续遍历解析
			candidateNames = newCandidateNames;
		}
	}
	while (!candidates.isEmpty());

	// 到这里已经把配置类解析完毕了。
	// 将ImportRegistry  注册为 bean,以支持ImportAware @Configuration 类
	if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
		sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
	}

	// 清除缓存
	if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
		// Clear cache in externally provided MetadataReaderFactory; this is a no-op
		// for a shared cache since it'll be cleared by the ApplicationContext.
		((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
	}
}

总结

  • 获取已经注册的Bean, 并筛选出配置类
  • 按照@Order进行排序,得到配置类集合configCandidates
  • 调用最核心的方法parse(),开始解析
    • 注意这是一个循环解析方法,当解析完一批bean后,可能会产生新的bean
    • 举个例子,在@Configuration中配置了一个@Bean
    • 而该bean也是配置类,或者@ComponentScan扫描到了新的配置类
    • 这些配置类在程序入口的时候并未传入,是后续扫描出来的
    • 所以需要循环遍历,直到处理完所有的配置类

1、checkConfigurationClassCandidate筛选配置类

  • 在checkConfigurationClassCandidate中,配置类的类型分为两种,Full 和 Lite,即完整的配置类和精简的配置类
    • Full : 即类被 @Configuration 注解修饰 && proxyBeanMethods属性为true (默认为 true)
      • Full 配置类就是我们常规使用的配置类
    • Lite : 被 @Component@ComponentScan@Import@ImportResource 修饰的类 或者 类中有被@Bean修饰的方法
      • Lite 配置类就是一些需要其他操作引入一些bean 的类
// metadataReaderFactory:元数据读取工厂
public static boolean checkConfigurationClassCandidate(
		BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
	// 获取className
	String className = beanDef.getBeanClassName();
	if (className == null || beanDef.getFactoryMethodName() != null) {
		return false;
	}

	// 解析关于当前被解析类的 注解元数据
	AnnotationMetadata metadata;
	// 如果当前BeanDefinition是AnnotatedBeanDefinition直接获取注解元数据即可
	if (beanDef instanceof AnnotatedBeanDefinition &&
			className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
		// Can reuse the pre-parsed metadata from the given BeanDefinition...
		metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
	}
	
	else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
		Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
		// 如果当前类是 BeanFactoryPostProcessor、BeanPostProcessor
		// AopInfrastructureBean、EventListenerFactory 类型不当做配置类处理,返回false
		if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
				BeanPostProcessor.class.isAssignableFrom(beanClass) ||
				AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
				EventListenerFactory.class.isAssignableFrom(beanClass)) {
			return false;
		}
		// 获取数据
		metadata = AnnotationMetadata.introspect(beanClass);
	}
	else {
	// 按照默认规则解析
		try {
			MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
			metadata = metadataReader.getAnnotationMetadata();
		}
		catch (IOException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Could not find class file for introspecting configuration annotations: " +
						className, ex);
			}
			return false;
		}
	}

	
	// 获取bean上的Configuration 注解的属性。如果没有被 @Configuration 修饰 config 则为null
	Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
	// 如果被 @Configuration 修饰 &&  proxyBeanMethods 属性为 true
	// @Configuration 的 proxyBeanMethods  属性默认值即为 true。
	if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
		// 设置 CONFIGURATION_CLASS_ATTRIBUTE 为 full
		beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
	}
	// 如果被 @Configuration 修饰 &&  isConfigurationCandidate(metadata) = true
	// 关于  isConfigurationCandidate(metadata) 的解析在下面
	else if (config != null || isConfigurationCandidate(metadata)) {
		// 设置 CONFIGURATION_CLASS_ATTRIBUTE 为 lite
		beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
	}
	else {
		return false;
	}

	// 按照@Order注解设置bean定义的排序属性值
	Integer order = getOrder(metadata);
	if (order != null) {
		beanDef.setAttribute(ORDER_ATTRIBUTE, order);
	}
	return true;
}

isConfigurationCandidate() Lite配置类筛选

// candidateIndicators  的定义
private static final Set<String> candidateIndicators = new HashSet<>(8);

static {
	candidateIndicators.add(Component.class.getName());
	candidateIndicators.add(ComponentScan.class.getName());
	candidateIndicators.add(Import.class.getName());
	candidateIndicators.add(ImportResource.class.getName());
}	

public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
	// 不能是接口
	if (metadata.isInterface()) {
		return false;
	}

	// 被 candidateIndicators 中的注解修饰。其中 candidateIndicators  注解在静态代码块中加载了
	for (String indicator : candidateIndicators) {
		if (metadata.isAnnotated(indicator)) {
			return true;
		}
	}

	try {
		// 类中包含被 @Bean 注解修饰的方法
		return metadata.hasAnnotatedMethods(Bean.class.getName());
	}
	catch (Throwable ex) {
		if (logger.isDebugEnabled()) {
			logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
		}
		return false;
	}
}

获取@Order注解属性值

public static Integer getOrder(AnnotationMetadata metadata) {
	Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
	return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null);
}

2、parser.parse(candidates) 解析配置类

  • 调用parse()方法为入口,可以看到有很多重载方法
  • 最底层都会根据bean定义生成一个ConfigurationClass对象传入processConfigurationClass方法
public void parse(Set<BeanDefinitionHolder> configCandidates) {
   for (BeanDefinitionHolder holder : configCandidates) {
      BeanDefinition bd = holder.getBeanDefinition();
      try {
         // 根据bean定义的类型走不同参数的重载parse方法
         if (bd instanceof AnnotatedBeanDefinition) {
            parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
         }
         else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
            parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
         }
         else {
            parse(bd.getBeanClassName(), holder.getBeanName());
         }
      }
      catch (BeanDefinitionStoreException ex) {
         throw ex;
      }
      catch (Throwable ex) {
         throw new BeanDefinitionStoreException(
               "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
      }
   }

   this.deferredImportSelectorHandler.process();
}

protected final void parse(@Nullable String className, String beanName) throws IOException {
   Assert.notNull(className, "No bean class name for configuration class bean definition");
   MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
   processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
}

protected final void parse(Class<?> clazz, String beanName) throws IOException {
   processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
}

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
   processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

processConfigurationClass()方法

  • this.conditionEvaluator.shouldSkip():解析@Conditional注解,判断是否应该跳过当前类的解析
  • Spring规则 :自身注入方式优先于引入方式(被 @Import 或者其他配置类引入)
    • 当一个类被多次引入时,会使用自身注入的方式的bean替代被引入方式的bean
    • 如果二者都是引入方式,则进行合并
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
	// 判断是否应该跳过当前类的解析。这里面解析了 @Conditional 注解
	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
		return;
	}
	// 判断是否已经解析过。configurationClasses 中保存着已经解析过的配置类
	// 在下面解析过的类都会被保存到 configurationClasses 中
	// 这里应该是 注入的配置类优先级高于引入的配置类
	// 如果配置类被多次引入则合并属性
	ConfigurationClass existingClass = this.configurationClasses.get(configClass);
	if (existingClass != null) {
		// 一个类被重复解析,那么可能被重复引入了,可能是通过@Import注解或者嵌套在其他配置类中被引入
		// 如果这两者都是通过这种方式被引入,那么则进行引入合并
		// 如果当前配置类和之前解析过的配置类都是引入的,则直接合并
		if (configClass.isImported()) {
			if (existingClass.isImported()) {
				existingClass.mergeImportedBy(configClass);
			}
			// 否则,忽略新导入的配置类;现有的非导入类将覆盖它
			return;
		}else {
			// 如果当前的配置类不是引入的,则移除之前的配置类,重新解析
			this.configurationClasses.remove(configClass);
			this.knownSuperclasses.values().removeIf(configClass::equals);
		}
	}

	// 递归处理配置类及其超类层次结构
	SourceClass sourceClass = asSourceClass(configClass, filter);
	do {
		sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
	}
	while (sourceClass != null);
	// 保存解析过的配置类
	this.configurationClasses.put(configClass, configClass);
}

doProcessConfigurationClass() 注解解析

@Nullable
protected final SourceClass doProcessConfigurationClass(
		ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
		throws IOException {
	// 1. 处理 @Component 注解
	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
		// Recursively process any member (nested) classes first
		processMemberClasses(configClass, sourceClass, filter);
	}

	// 2. 处理 @PropertySource 注解
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), PropertySources.class,
			org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			processPropertySource(propertySource);
		}
		else {
			logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
					"]. Reason: Environment must implement ConfigurableEnvironment");
		}
	}

	// 3. 处理 @ComponentScan注解
	Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
	if (!componentScans.isEmpty() &&
			!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
		for (AnnotationAttributes componentScan : componentScans) {
			// The config class is annotated with @ComponentScan -> perform the scan immediately
			Set<BeanDefinitionHolder> scannedBeanDefinitions =
					this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
			// Check the set of scanned definitions for any further config classes and parse recursively if needed
			for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
				BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
				if (bdCand == null) {
					bdCand = holder.getBeanDefinition();
				}
				if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
					parse(bdCand.getBeanClassName(), holder.getBeanName());
				}
			}
		}
	}

	// 4. 处理 @Import 注解
	processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

	// 5. 处理 @ImportResource 注解
	AnnotationAttributes importResource =
			AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
	if (importResource != null) {
		String[] resources = importResource.getStringArray("locations");
		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
		for (String resource : resources) {
			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
			configClass.addImportedResource(resolvedResource, readerClass);
		}
	}

	// 6. 处理 @Bean修饰的方法
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

	// 处理其他默认接口方法
	// 检测配置类实现的接口中的默认方法是否被@Bean修饰,如果被修饰则也需要保存到 configClass 中
	processInterfaces(configClass, sourceClass);

	// 处理父类,如果存在
	// 如果存在父类,则将父类返回,对父类进行解析
	if (sourceClass.getMetadata().hasSuperClass()) {
		String superclass = sourceClass.getMetadata().getSuperClassName();
		if (superclass != null && !superclass.startsWith("java") &&
				!this.knownSuperclasses.containsKey(superclass)) {
			this.knownSuperclasses.put(superclass, configClass);
			// Superclass found, return its annotation metadata and recurse
			return sourceClass.getSuperClass();
		}
	}

	// No superclass -> processing is complete
	return null;
}

2.1、处理@Component注解的内部类

  • 如果当前类是被@Component修饰,则需要判断其内部类是否需要解析
	// 首先判断如果配置类被@Component 修饰,则调用processMemberClasses 方法处理
	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
		// Recursively process any member (nested) classes first
		processMemberClasses(configClass, sourceClass, filter);
	}
  • 如果配置类中有内部类,则判断其内部类是否是配置类,如果是则递归去解析新发现的内部配置类
    • 过滤内部类是否满足lite的配置类规则,并未校验 full的规则
    • lite规则 : 被 @Component@ComponentScan@Import@ImportResource 修饰的类 或者 类中有被@Bean修饰的方法
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
		Predicate<String> filter) throws IOException {
	// 获取内部类
	Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
	if (!memberClasses.isEmpty()) {
		// 如果有内部类,则遍历内部类,判断内部类是否是配置类,如果是,则添加到 candidates 集合中。
		List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
		for (SourceClass memberClass : memberClasses) {
			// 这里判断的是是否是lite类型的配置类
			if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
					!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
				candidates.add(memberClass);
			}
		}
		// 进行排序
		OrderComparator.sort(candidates);
		for (SourceClass candidate : candidates) {
			// importStack 用来缓存已经解析过的内部类,这里处理循环引入问题。
			if (this.importStack.contains(configClass)) {
				// 打印循环引用异常
				this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
			}
			else {
				// 解析前入栈,防止循环引入
				this.importStack.push(configClass);
				try {
					// 递归去解析新发现的配置类
					processConfigurationClass(candidate.asConfigClass(configClass), filter);
				}
				finally {
					// 解析完毕出栈
					this.importStack.pop();
				}
			}
		}
	}
}

2.2、处理@PropertySource注解

  • @PropertySource 注解可以引入配置文件使用
  • 在这里进行@PropertySource注解的解析,将引入的配置文件加载到环境变量中
	// 去重后遍历 PropertySource 注解所指向的属性。注意这里有两个注解@PropertySources 和 @PropertySource。
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), PropertySources.class,
			org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			// 解析PropertySource  注解
			processPropertySource(propertySource);
		}
		else {
			logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
					"]. Reason: Environment must implement ConfigurableEnvironment");
		}
	}
  • processPropertySource 代码如下,在这里解析每一个@PropertySource注解属性
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
	// 获取 @PropertySource 注解的各个属性
	String name = propertySource.getString("name");
	if (!StringUtils.hasLength(name)) {
		name = null;
	}
	String encoding = propertySource.getString("encoding");
	if (!StringUtils.hasLength(encoding)) {
		encoding = null;
	}
	// 获取指向的文件路径
	String[] locations = propertySource.getStringArray("value");
	Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
	boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");

	Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
	PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
			DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
	// 遍历文件路径
	for (String location : locations) {
		try {
			//  根据路径获取到资源文件并保存到environment 中
			// 解决占位符,获取真正路径
			String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
			Resource resource = this.resourceLoader.getResource(resolvedLocation);
			//保存 PropertySource 到 environment 中
			addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
		}
		catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
			// Placeholders not resolvable or resource not found when trying to open it
			if (ignoreResourceNotFound) {
				if (logger.isInfoEnabled()) {
					logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
				}
			}
			else {
				throw ex;
			}
		}
	}
}

2.3、处理@ComponentScan @ComponentScans注解

  • this.componentScanParser.parse()扫描方法其实就是调用scanner.doScan()。Spring源码解析(二):bean容器的创建、默认后置处理器、扫描包路径bean
  • 这里校验是否是配置类,校验了fulllite的规则,和处理 @Component 中的内部类的规则并不相同
  • 如果扫描到的bean中发现了新的配置类,则递归去解析
	// 这里会将 @ComponentScans 中的多个 @ComponentScan 也解析出来封装成一个个AnnotationAttributes对象
	Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
	// 如果当前配置类被 @componentScans 或 @componentScan 注解修饰 && 不应跳过(符合@Conditional条件)
	if (!componentScans.isEmpty() &&
			!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			// 遍历 @ComponentScans、 @ComponentScan
		for (AnnotationAttributes componentScan : componentScans) {
			// 直接执行扫描,根据指定路径扫描出来bean。
			Set<BeanDefinitionHolder> scannedBeanDefinitions =
					this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
			// 遍历扫描出来的bean
			for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
			// 获取原始的bean的定义
				BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
				if (bdCand == null) {
					bdCand = holder.getBeanDefinition();
				}
				// 检测如果是配置类,则递归调用 parse 解析。
				if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
					parse(bdCand.getBeanClassName(), holder.getBeanName());
				}
			}
		}
	}

2.4、处理@Import 注解

  • @Import注入bean的不同方式
    • @Import:通过@Import(XXX.class) 的方式,将指定的类注册到容器中
    • @Import + ImportSelector/DeferredImportSelector:将 ImportSelector#selectImports方法返回的内容通过反射加载到容器中
    • @Import + ImportBeanDefinitionRegistrar:通过registerBeanDefinitions方法声明BeanDefinition 并自己注册到Spring容器中
  • 如果是第三种方式,这里只是将ImportBeanDefinitionRegistrar的实现类创建出来保存到configClass,后面处理
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
		Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
		boolean checkForCircularImports) {
	// importCandidates 是通过getImports() 方法解析 @Import 注解而来, 如果为空则说明没有需要引入的直接返回
	if (importCandidates.isEmpty()) {
		return;
	}
	// 检测是否是循环引用。
	if (checkForCircularImports && isChainedImportOnStack(configClass)) {
		this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
	}
	else {
		// 解析前先入栈,防止循环引用
		this.importStack.push(configClass);
		try {
			for (SourceClass candidate : importCandidates) {
				// 判断是否是ImportSelector类型。ImportSelector 则需要调用selectImports 方法来获取需要注入的类。
				if (candidate.isAssignable(ImportSelector.class)) {
					// Candidate class is an ImportSelector -> delegate to it to determine imports
					Class<?> candidateClass = candidate.loadClass();
					ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
							this.environment, this.resourceLoader, this.registry);
					Predicate<String> selectorFilter = selector.getExclusionFilter();
					if (selectorFilter != null) {
						exclusionFilter = exclusionFilter.or(selectorFilter);
					}
					if (selector instanceof DeferredImportSelector) {
						this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
					}
					else {
					// 调用 selectImports 方法获取需要引入的类,并递归再次处理。
						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
						// 递归解析
						processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
					}
				}
				// 如果是ImportBeanDefinitionRegistrar类型,则委托它注册其他bean定义
				else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
					Class<?> candidateClass = candidate.loadClass();
					ImportBeanDefinitionRegistrar registrar =
							ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
									this.environment, this.resourceLoader, this.registry);
					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
				}
				else {
					// 不是ImportSelector或ImportBeanDefinitionRegistrar
					// 将其作为@Configuration类进行处理
					this.importStack.registerImport(
							currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
					// 否则递归处理需要引入的类。
					processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
				}
			}
		}
		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();
		}
	}
}

2.5、处理@ImportResource注解

  • @ImportResource注解用于导入配置文件,如:spring-mvc.xml、application-Context.xml
  • 这里只是保存到configClass中,后面处理
	AnnotationAttributes importResource =
			AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
	if (importResource != null) {
		String[] resources = importResource.getStringArray("locations");
		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
		for (String resource : resources) {
			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
			configClass.addImportedResource(resolvedResource, readerClass);
		}
	}

2.6、处理 @Bean修饰的方法

  • 这里也只是保存到configClass,后面应该会统一处理
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

3、this.reader.loadBeanDefinitions(configClasses) 加载bean定义

  • 上一步将各种注解的属性值都解析了出来,并保存到了configClass的各种属性中
  • 下面才开始处理
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
	TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
	for (ConfigurationClass configClass : configurationModel) {
		loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
	}
}
  • 每个部分的解析都封装到了不同的方法中
private void loadBeanDefinitionsForConfigurationClass(
		ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
	// 判断是否应该跳过
	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;
	}
	// 1. 如果配置是被引入的(被 @Import 或者其他配置类内部引入)
	if (configClass.isImported()) {
		registerBeanDefinitionForImportedConfigurationClass(configClass);
	}
	// 2. 遍历配置类中的所有 BeanMethod方法
	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		loadBeanDefinitionsForBeanMethod(beanMethod);
	}
	// 3. 加载 通过 @ImportResource 的 获取的bean
	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
	// 4. 加载 通过 @Import 的 获取的bean
	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

registerBeanDefinitionForImportedConfigurationClass

  • 这一步就是将引入的配置类注册为BeanDefinition
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
	AnnotationMetadata metadata = configClass.getMetadata();
	AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
	
	ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
	configBeanDef.setScope(scopeMetadata.getScopeName());
	String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
	AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
	// 创建代理,根据 scopeMetadata 的代理模式。默认不创建代理。
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	// 注册了BeanBeanDefinition 。这里将BeanDefinition保存到了 DefaultListableBeanFactory#beanDefinitionMap 中
	this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
	configClass.setBeanName(configBeanName);

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

loadBeanDefinitionsForBeanMethod

  • 操作@Bean方法
  • 基本上就是解析各种注解,创建对应的 BeanDefinition 并注册
    • @Lazy、@Primary、@DependsOn、@Role、@Description、@Scope
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
	// 获取别名
	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)?
	// 判断是否已经被定义过
	if (isOverriddenByExistingDefinition(beanMethod, 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;
	}
	// 定义配置类的  BeanDefinition
	ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
	beanDef.setResource(configClass.getResource());
	beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
	// 处理静态 @Bean 方法和 非静态 @Bean 方法
	if (metadata.isStatic()) {
		// static @Bean method
		if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
			beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
		}
		else {
			beanDef.setBeanClassName(configClass.getMetadata().getClassName());
		}
		// 设置唯一工厂方法名称
		beanDef.setUniqueFactoryMethodName(methodName);
	}
	else {
		// instance @Bean method
		// 指定要使用的工厂bean(如果有)。这是用于调用指定工厂方法的bean的名称
		beanDef.setFactoryBeanName(configClass.getBeanName());
		// 设置唯一工厂方法名称,内部调用了 setFactoryMethodName(name); 保存 FactoryMethodName
		beanDef.setUniqueFactoryMethodName(methodName);
	}

	if (metadata instanceof StandardMethodMetadata) {
		beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
	}
	// 设置构造模式 构造注入
	beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
	// 设置跳过属性检查
	beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
			SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
	// 处理通用的注解: @Lazy、@Primary、@DependsOn、@Role、@Description。设置到 BeanDefinition 中
	AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
	// 获取注解的其他属性并设置到 BeanDefinition
	Autowire autowire = bean.getEnum("autowire");
	if (autowire.isAutowire()) {
		beanDef.setAutowireMode(autowire.value());
	}

	boolean autowireCandidate = bean.getBoolean("autowireCandidate");
	if (!autowireCandidate) {
		beanDef.setAutowireCandidate(false);
	}

	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);
	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
	BeanDefinition beanDefToRegister = beanDef;
	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.isTraceEnabled()) {
		logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
				configClass.getMetadata().getClassName(), beanName));
	}
	// 注册BeanDefinition
	this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}

loadBeanDefinitionsFromImportedResources

  • 从导入的资源加载Bean定义
  • 即通过解析@ImportResource注解引入的资源文件,获取到BeanDefinition 并注册
private void loadBeanDefinitionsFromImportedResources(
		Map<String, Class<? extends BeanDefinitionReader>> importedResources) {

	Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();
	// 遍历引入的资源文件
	importedResources.forEach((resource, readerClass) -> {
		// Default reader selection necessary?
		if (BeanDefinitionReader.class == readerClass) {
			// 处理 .groovy 类型文件
			if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
				// When clearly asking for Groovy, that's what they'll get...
				readerClass = GroovyBeanDefinitionReader.class;
			}
			else {
				// Primarily ".xml" files but for any other extension as well
				// 这里使用 XmlBeanDefinitionReader 类型来解析
				readerClass = XmlBeanDefinitionReader.class;
			}
		}
		// 从缓冲中获取
		BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
		// 如果缓存中没有,则创建一个 reader 用于 resource 的解析。
		if (reader == null) {
			try {
				// Instantiate the specified BeanDefinitionReader
				reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
				// Delegate the current ResourceLoader to it if possible
				if (reader instanceof AbstractBeanDefinitionReader) {
					AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
					abdr.setResourceLoader(this.resourceLoader);
					abdr.setEnvironment(this.environment);
				}
				readerInstanceCache.put(readerClass, reader);
			}
			catch (Throwable ex) {
				throw new IllegalStateException(
						"Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
			}
		}

		// TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations
		// 解析resource资源中的内容
		reader.loadBeanDefinitions(resource);
	});
}

loadBeanDefinitionsFromRegistrars

  • 注册了@Import + ImportBeanDefinitionRegistrar注解引入的内容
  • 之前只是将ImportBeanDefinitionRegistrar的实现类创建处理,这里才调用registerBeanDefinitions方法注册bean定义
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
	registrars.forEach((registrar, metadata) ->
			registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}

三、postProcessBeanFactory()(cglib代理配置类)

解决问题及示例

  • ConfigurationClassPostProcessor#postProcessBeanFactory方法通过cglib代理配置类,来拦截 @Bean修饰的方法
  • 目的是为了在配置类中多次调用@Bean方法返回的是同一个结果
  • 即在下面的代码中 person1() 和 person2() 方法中调用的user() 方法返回的结果是同一个值
  • 避免了单例模式下的多例创建
@Configuration
public class Config {
	@Bean
	public User user() {
		return new User();
	}
	@Bean
	public Person person1() {
		System.out.println("person1: " + user());
		return new Person();
	}
	@Bean
	public Person person2() {
		System.out.println("person2: " + user());
		return new Person();
	}
}

输出结果:

person1: com.xc.bean.User@16267862
person2: com.xc.bean.User@16267862

具体原因,因为在postProcessBeanFactory方法中对Full类型(即被@Configuration修饰的配置类)的配置类进行了动态代理

1、postProcessBeanFactory方法内容

  • 对配置类进行增强
  • 创建ImportAwareBeanPostProcessor 来支持ImportAware接口
/**
 * 准备配置类,以便在运行时为Bean请求提供服务,方法是将它们替换为CGLIB增强的子类
 */
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	int factoryId = System.identityHashCode(beanFactory);
	if (this.factoriesPostProcessed.contains(factoryId)) {
		throw new IllegalStateException(
				"postProcessBeanFactory already called on this post-processor against " + beanFactory);
	}
	this.factoriesPostProcessed.add(factoryId);
	if (!this.registriesPostProcessed.contains(factoryId)) {
		// 这里还是解析配置类,只有还没有解析的时候才会调用下面的
		processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
	}
	// 增强配置类(核心方法)
	enhanceConfigurationClasses(beanFactory);
	// 添加实例化后置处理器
	beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

2、enhanceConfigurationClasses 方法用于增强配置类

  • Spring会对Full Configuration (即被@Configuration修饰的配置类)进行代理,拦截@Bean方法,以确保正确处理@Bean语义
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
	Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
	for (String beanName : beanFactory.getBeanDefinitionNames()) {
		BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
		// 获取 CONFIGURATION_CLASS_ATTRIBUTE属性,如果不为null,则是配置类,在上篇中有过交代(可能是full或者lite类型)
		Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
		MethodMetadata methodMetadata = null;
		if (beanDef instanceof AnnotatedBeanDefinition) {
			methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
		}
		// 如果是配置类(configClassAttr  != null) || @Bean注解派生的方法(methodMetadata != null 不为空表示 FactoryMethod不为空,则可以说明是 @Bean 生成的 BeanDefinition)
		if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
			// Configuration class (full or lite) or a configuration-derived @Bean method
			// -> resolve bean class at this point...
			AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
			// 这里判断如果指定的 bean(注意并非这里的abd,而是abd所要生成的bean) 如果不是 Class类型则进入 if里面
			if (!abd.hasBeanClass()) {
				try {
					// 解析 beanClass,即获取这个 Bean 的Class 并保存到 abd中
					abd.resolveBeanClass(this.beanClassLoader);
				}
				catch (Throwable ex) {
					throw new IllegalStateException(
							"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
				}
			}
		}
		// 对 FUll的 配置类进行处理!!!
		if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
			// 对非AbstractBeanDefinition子类的情况直接抛出异常
			if (!(beanDef instanceof AbstractBeanDefinition)) {
				throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
						beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
			}
			else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
				logger.info("Cannot enhance @Configuration bean definition '" + beanName +
						"' since its singleton instance has been created too early. The typical cause " +
						"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
						"return type: Consider declaring such methods as 'static'.");
			}
			// 保存下来,准备代理
			configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
		}
	}
	// 如果没有找到 full 配置类,则说明不需要代理增强,则直接返回。
	if (configBeanDefs.isEmpty()) {
		// nothing to enhance -> return immediately
		return;
	}
	// 创建增强对象
	ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
	// 进行配置类增强。这里的增强实际上是通过cglib对配置类进行了代理。
	for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
		AbstractBeanDefinition beanDef = entry.getValue();
		// If a @Configuration class gets proxied, always proxy the target class
		// 设置 :如果配置类被代理,则该 bean也需要一直代理
		beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
		// Set enhanced subclass of the user-specified bean class
		// 获取bean的 Class 类
		Class<?> configClass = beanDef.getBeanClass();
		// 生成代理类
		Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
		if (configClass != enhancedClass) {
			if (logger.isTraceEnabled()) {
				logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
						"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
			}
			 //将BeanClass设置为增强后的类
			beanDef.setBeanClass(enhancedClass);
		}
	}
}

enhancer.enhance(configClass, this.beanClassLoader)生成代理类

// 加载指定的类并为其生成一个CGLIB子类,该子类配备了能够识别作用域和其他bean语义的容器感知回调。
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
	// 如果是 EnhancedConfiguration子类,则说明已经被增强(代理),直接返回
	if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
		... 忽略日志打印
		return configClass;
	}
	// 创建代理类
	Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
	if (logger.isTraceEnabled()) {
		logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
				configClass.getName(), enhancedClass.getName()));
	}
	return enhancedClass;
}

private Class<?> createClass(Enhancer enhancer) {
	Class<?> subclass = enhancer.createClass();
	// Registering callbacks statically (as opposed to thread-local)
	// is critical for usage in an OSGi environment (SPR-5932)...
	// 指定代理回调 为 CALLBACKS
	Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
	return subclass;
}

回调函数:声明的三个拦截器

private static final Callback[] CALLBACKS = new Callback[] {
	// 拦截@Bean方法的调用,以确保正确处理@Bean语义
	new BeanMethodInterceptor(),
	// BeanFactoryAware#setBeanFactory的调用,用于获取BeanFactory对象
	new BeanFactoryAwareMethodInterceptor(),
	NoOp.INSTANCE
};

BeanMethodInterceptor#intercept拦截方法

  • 主要作用是:拦截@Bean方法的调用,以确保正确处理@Bean语义
  • 当调用@Bean方法时,就会被以下代码所拦截
//BeanMethodInterceptor#intercept源码
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
                        MethodProxy cglibMethodProxy) throws Throwable {

    // enhancedConfigInstance 已经是配置类的增强对象了,在增强对象中,有beanFactory字段的
    // 获取增强对象中的beanFactory
    ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
    // 获取beanName
    String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

    // Determine whether this bean is a scoped-proxy
    if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
        String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
        if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
            beanName = scopedBeanName;
        }
    }

    // 检查容器中是否存在对应的 FactoryBean 如果存在,则创建一个增强类
    // 通过创建增强类来代理拦截 getObject()的调用 , 以确保了FactoryBean的语义
    if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
            factoryContainsBean(beanFactory, beanName)) {
        Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
        if (factoryBean instanceof ScopedProxyFactoryBean) {
            // Scoped proxy factory beans are a special case and should not be further proxied
        } else {
            // It is a candidate FactoryBean - go ahead with enhancement
            // 创建增强类,来代理 getObject()的调用
            // 有两种可选代理方式,cglib 和 jdk
            // Proxy.newProxyInstance(
            //                    factoryBean.getClass().getClassLoader(), new Class<?>[]{interfaceType},
            //                    (proxy, method, args) -> {
            //                        if (method.getName().equals("getObject") && args == null) {
            //                            return beanFactory.getBean(beanName);
            //                        }
            //                        return ReflectionUtils.invokeMethod(method, factoryBean, args);
            //                    });
            return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
        }
    }

    // 判断当时执行的方法是否为@Bean方法本身
    // 举个例子 : 如果是直接调用@Bean方法,也就是Spring来调用我们的@Bean方法,则返回true
    // 如果是在别的方法内部,我们自己的程序调用 @Bean方法,则返回false
    if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
        // The factory is calling the bean method in order to instantiate and register the bean
        // (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
        // create the bean instance.
        if (logger.isInfoEnabled() &&
                BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
            logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
                            "assignable to Spring's BeanFactoryPostProcessor interface. This will " +
                            "result in a failure to process annotations such as @Autowired, " +
                            "@Resource and @PostConstruct within the method's declaring " +
                            "@Configuration class. Add the 'static' modifier to this method to avoid " +
                            "these container lifecycle issues; see @Bean javadoc for complete details.",
                    beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
        }
        // 如果返回true,也就是Spring在调用这个方法,那么就去真正执行该方法
        return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
    }

    //否则,则尝试从容器中获取该 Bean 对象
    // 怎么获取呢? 通过调用 beanFactory.getBean 方法
    // 而这个getBean 方法,如果对象已经创建则直接返回,如果还没有创建,则创建,然后放入容器中,然后返回
    return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}

3、总结

执行流程

在这里插入图片描述

替换bean定义class为代理对象class

在这里插入图片描述

赋值beanFactory(后面会调用getBean方法)

在这里插入图片描述

调用@Bean方法即从bean容器中获取对象

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/831343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构 | 搜索和排序——排序

目录 一、冒泡排序 二、选择排序 三、插入排序 四、希尔排序 五、归并排序 六、快速排序 排序是指将集合中的元素按照某种顺序排序的过程。 一、冒泡排序 冒泡排序多次遍历列表。它比较相邻的元素&#xff0c;将不合顺序的交换。每一轮遍历都将下一个最大值放到正确的位…

校园跑腿小程序运营攻略

作为一名校园跑腿小程序的运营者&#xff0c;你可能会面临诸如用户获取、平台推广、服务质量保证等挑战。在本篇推文中&#xff0c;我将为你提供一些关键的运营策略&#xff0c;帮助你成功运营校园跑腿小程序。 1. 用户获取和留存 用户是校园跑腿小程序成功的关键。以下是一些…

非凸科技受邀参加中科大线上量化分享

7月30日&#xff0c;非凸科技受邀参加由中国科学技术大学管理学院学生会、超级量化共同组织的“打开量化私募的黑箱”线上活动&#xff0c;分享量化前沿以及求职经验&#xff0c;助力同学们拿到心仪的offer。 活动上&#xff0c;非凸科技量化策略负责人陆一洲从多个角度分享了如…

基于Windows手动编译openssl和直接安装openssl

零、环境 win10-64位 VS2019 一、手动编译 1、安装perl https://platform.activestate.com/ActiveState-Projects/ActiveState-Perl-5.36.0 两种方法都没能成功。。第一种下载后会得到一个 state-remote-installer.exe&#xff0c;然后安装时会在命令行中执行&#xff0c;…

PtahDAO:全球首个DAO治理资产信托计划的金融平台

金融科技是当今世界最具创新力和影响力的领域之一&#xff0c;区块链技术作为金融科技的核心驱动力&#xff0c;正在颠覆传统的金融模式&#xff0c;为全球用户提供更加普惠、便捷、安全的金融服务。在这个变革的浪潮中&#xff0c;PtahDAO&#xff08;普塔道&#xff09;作为全…

UMS攸信入选2023年先进制造业倍增计划企业名单,为企业发展增添新助力!

根据《厦门市人民政府关于印发先进制造业倍增计划实施方案&#xff08;2022-2026年&#xff09;的通知》&#xff08;厦府规〔2022〕3号&#xff09;&#xff0c;经市政府专题会研究&#xff0c;确定2023年先进制造业倍增计划企业名单。 关于2023年先进制造业倍增计划企业名单和…

【知网检索】2023年金融,贸易和商业管理国际学术会议(FTBM2023)

随着经济全球化&#xff0c;贸易自由化的进程加快&#xff0c;我国经济对外开放程度不断加深&#xff0c;正在加快融入世界经济一体化当中。当今世界各国竞争过程中&#xff0c;金融、贸易以及商业形态已成为其关键与焦点竞争内容。 2023年金融、贸易和商业管理国际学术会议(F…

百度飞桨助力高校培养AI大模型人才,2023年飞桨产学合作项目申报启动

7月7日&#xff0c;教育部产学合作协同育人项目公布项目指南通过的企业名单&#xff0c;百度被列入2023年&#xff08;5月&#xff09;批次名单&#xff1b;其中百度飞桨与文心大模型项目40个&#xff0c;包含教学内容和课程体系改革、实践条件和实践基地建设、师资培训项目三大…

途游游戏 x 极狐GitLab “通关” DevOps :单元测试从无到优,覆盖率 0→80%

目录 4 个工具孤岛 → 极狐GitLab 全家桶&#xff0c; 被动的「人找进度」 → 高效的「进度找人」 把 Code Review 做扎实 代码质量「向左移」&#xff0c;修复成本「往下降」 从无到「优」 自动执行单元测试&#xff0c;覆盖率 0→80% 你喜欢玩游戏吗&#xff1f; 最近…

概念辨析 | SAR运动补偿和自聚焦技术:深入探索雷达图像

注1:本文系“概念辨析”系列之一,致力于简洁清晰地解释、对比复杂而专业的概念。本次辨析的概念是:合成孔径雷达(SAR)的运动补偿和自聚焦技术。 SAR运动补偿和自聚焦技术:深入探索雷达图像 Synthetic Aperture Radar (SAR) 1 背景介绍 合成孔径雷达(Synthetic Aperture R…

打印机地址换了怎么连接

原先的打印机地址&#xff1a;172.16.17.10 添加新打印机地址&#xff1a;winR打开&#xff0c;在运行里输入更改后的地址&#xff08;\\ip&#xff09;\\172.16.17.40确定&#xff0c;右键链接。就可以在你要用到的地方看到这个设备了

ESD防静电监控系统在SMT产线中的应用案例

作为电子厂的关键制造环节之一&#xff0c;SMT&#xff08;表面贴装技术&#xff09;产线的效率和质量对企业的竞争力至关重要。为了提高生产线的管理效率和保障生产环境的质量&#xff0c;许多电子厂开始采用MES生产管理系统和ESD防静电监控系统的综合解决方案。 在SMT产线中安…

高电压功放的优点有哪些呢(高压放大器)

高电压功放是电子设备中的一种特殊类型的功率放大器&#xff0c;具有独特的优点&#xff0c;被广泛应用于各种领域。高电压功放可以将低电压信号放大到较高的电压水平&#xff0c;实现对大功率负载的驱动。下面我们来看看一下高电压功率放大器的优点。 1.宽电压范围 高电压功放…

8月3日上课内容 LNMP精讲

LNMP&#xff1a;目前成熟的企业网站的应用模式之一&#xff0c;指的是一套协作工作的系统和相关文件 能够提供静态页面服务&#xff0c;也可以提供动态web服务。 这是一个缩写 L linux系统&#xff0c;操作系统。 N nginx网站服务&#xff0c;前端&#xff0c;提供前端的静…

Dockerfile构建Redis镜像(yum方式)

目录 Dockerfile构建Redis镜像 1、建立工作目录 2、编写Dockerfile文件 3、构建镜像 4、测试容器 Dockerfile构建Redis镜像 1、建立工作目录 [roothuyang1 ~]# mkdir redis [roothuyang1 ~]# cd redis/ 2、编写Dockerfile文件 [roothuyang1 redis]# vim Dockerfile 配置如…

论文代码学习—HiFi-GAN(4)——模型训练函数train文件具体解析

文章目录 引言正文模型训练代码整体训练过程具体训练细节具体运行流程 多GPU编程main函数&#xff08;通用代码&#xff09;完整代码 总结引用 引言 这里翻译了HiFi-GAN这篇论文的具体内容&#xff0c;具体链接。这篇文章还是学到了很多东西&#xff0c;从整体上说&#xff0c…

Med-PaLM M走向通用医学AI(2023+Towards Generalist Biomedical AI)

摘要&#xff1a; 医学本质上是多模式的&#xff0c;具有丰富的数据模式&#xff0c;包括文本、成像、基因组学等。灵活编码、集成和大规模解释这些数据的通才生物医学人工智能(AI)系统可以潜在地实现从科学发现到医疗服务等有影响力的应用。为了使这些模型的发展&#xff0c;…

记录一个Spring自己注入自己的一个坑

问题代码如下&#xff1a; 原本是要在ActiveMqListener中注入ActiveMqSender方法的&#xff0c;在自动补全的时候没有注意&#xff0c;变成了图上的情况。 该问题会导致服务启动时卡住&#xff0c;不报错也没有异常信息。代码上也不会有任何提示。排查起来比较困难。在此特别记…

mysql 、sql server 常见的区别

&#xff2e;&#xff35;&#xff2c;&#xff2c;   处理 MySQL IFNULL(col , val) SQL Server ISNULL(col,val) 表名、列名等 一般不推荐用保留字 &#xff0c;如果非要保留字 MySQL 用用着重号&#xff0c;即 反引号 包括 select col from GROUP SQL Server 用用着重号…

2023-07月:人工智能趋势总结

疯狂AI周&#xff01; 我将详细介绍本周所有最重要的新闻&#xff0c;所以请坐下来&#xff0c;放松&#xff0c;享受更新&#xff01; 1. Android 版 ChatGPT 本周最令人兴奋的消息之一是宣布推出适用于 Android 的 ChatGPT 移动应用程序。 您已经可以从 Google Play 商店预…