Spring之配置类源码深度解析

2023-05-16

这篇文章是继《Spring之启动过程源码解析之后》,对Spring启动过程中用到的几个重要的方法进行详细的解读

目录

一、invokeBeanFactoryPostProcessors(),执行BeanFactoryPostProcessor

1. 方法说明

2. invokeBeanFactoryPostProcessors()内部执行流程

二、registerBeanPostProcessors(),向BeanFactory中注册BeanPostProcessor

1.方法说明

2. registerBeanPostProcessors()内部执行流程

三、postProcessBeanDefinitionRegistry()解析

1. 方法总览

2. 处理流程

四、关于@Configuration注解

1. 生成代理类

2. 代理类的作用

3. 总结


一、invokeBeanFactoryPostProcessors(),执行BeanFactoryPostProcessor

1. 方法说明

在Spring启动过程中,当执行到invokeBeanFactoryPostProcessors()这个方法的时候,就意味着要执行BeanFactoryPostProcessor了,此时在BeanFactory中会存在一个BeanFactoryPostProcessor: ConfigurationClassPostProcessor,它也是一个BeanDefinitionRegistryPostProcessor;

2. invokeBeanFactoryPostProcessors()内部执行流程

2.1. 获取BeanFactoryPostProcessors,并且执行通过ApplicationContext添加进来的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法,注意:这里获取到的是通过ApplicationContext的addBeanFactoryPostProcessor()添加的BeanFactoryPostProcessor,我们自己定义的BeanFactoryPostProcessor如果没有像这样设置,在这里是获取不到的,因为Spring也得通过扫描才能发现

2.2. 从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName, 匹配实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,这里匹配到的是ConfigurationClassPostProcessor,同时会调用BeanFactory的getBean方法,将ConfigurationClassPostProcessor的对象创建出来,并执行它的postProcessBeanDefinitionRegistry()方法,在这一步会得到BeanDefinition;

注意:在ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()方法会进行扫描,得到BeanDefinition并注册,下面会有关于这个方法的详细分析;

2.3. 从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName,匹配实现了Ordered接口的BeanDefinitionRegistryPostProcessor,执行BeanFactory中实现了Ordered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法;

说明:因为在上面那一步中,Spring就会进行扫描,所以这里从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName也包括我们自定义的;

2.4. 执行那些没有实现了PriorityOrdered或Ordered接口的普通BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法;

2.5. 执行上面所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法;

2.6. 执行通过ApplicationContext添加进来的BeanFactoryPostProcessor的 postProcessBeanFactory()方法;

2.7. 执行BeanFactory中实现了PriorityOrdered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法;

2.8. 执行BeanFactory中实现了Ordered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法;

2.9. 执行BeanFactory中其他的BeanFactoryPostProcessor的postProcessBeanFactory()方法;

二、registerBeanPostProcessors(),向BeanFactory中注册BeanPostProcessor

1.方法说明

因为上面的步骤完成了扫描,这个过程中开发者可能自己定义了一些BeanPostProcessor,在这一步就会把BeanFactory中所有的BeanPostProcessor找出来并实例化得到一个对象,并添加到BeanFactory中去(属性beanPostProcessors),最后再重新添加一个ApplicationListenerDetector对象(之前其实就添加过了,这里是为了把ApplicationListenerDetector移动到最后);

2. registerBeanPostProcessors()内部执行流程

2.1. 获取BeanFactory中所有实现了BeanPostProcessor接口的beanName;

2.2. 声明不同的集合并初始化,以便后面对BeanPostProcessor进行分类;

2.3. 遍历2.1 获取的beanName集合,对BeanPostProcessor进行分类:

 ① 首先根据beanName,匹配实现了PriorityOrdered接口的BeanPostProcessor, 并得到其实例对象,如果这个实例对象同时实现了MergedBeanDefinitionPostProcessor,还需要将它单独记录;

 ② 否则,匹配实现了Ordered接口的BeanPostProcessor,但是这里并没有去beanFactory中获取实例对象,而是将符合条件的beanName存到了一个集合中;

 ③ 如果不满足①②,则将没有实现任何排序接口的beanName也存到了一个集合中;

2.4. 对实现了PriorityOrdered接口的BeanPostProcessor实例进行排序,然后注册到beanFactory中(会存到beanPostProcessors这个List中);

2.5. 遍历实现了Ordered接口的BeanPostProcessor的beanName ,获取其实例,并添加到相应的集合中,如果实现了MergedBeanDefinitionPostProcessor则存放到相应的集合中,然后排序注册到beanFactory中;

2.6. 遍历剩余实现了BeanPostProcessor接口beanName ,获取其实例添加到相应的集合中,如果实现了MergedBeanDefinitionPostProcessor则存放到相应的集合中 , 然后注册到beanFactory中;

2.7. 将前面收集到的实现了MergedBeanDefinitionPostProcessor的BeanPostProcessor实例进行排序,重新注册到beanFactory中;

2.8. 将ApplicationListenerDetector注册到beanFactory中,在prepareBeanFactory(beanFactory)方法中,Spring其实就已经将ApplicationListenerDetector注册到了beanFactory中,这里重新注册,目的是将它放到最后;

说明:Spring将MergedBeanDefinitionPostProcessor排在最后,是因为Spring把这些MergedBeanDefinitionPostProcessor当做是Spring内部的BeanPostProcessors,这里可能存在一个用户优先的原则;

/**
 * 向BeanFactory中注册BeanPostProcessor
 */
public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		/**
		 * 获取BeanFactory中所有实现了BeanPostProcessor接口的beanName
		 * 不包括prepareBeanFactory(beanFactory)这一步添加到beanFactory中的三个BeanPostProcessor实例对象
		 * 这三个实例对象在Spring进行扫描之前就已经添加到了beanPostProcessors这个list中
		 */
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
	    //beanProcessorTargetCount表示BeanFactory中所有的BeanPostProcessor数量,+1表示BeanPostProcessorChecker
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		/**
		 * 存放实现了PriorityOrdered接口的BeanPostProcessor实例
		 */
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		/**
		 * 存放实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor实例
		 * 主要是Spring内部的BeanPostProcessor,例如:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor
		 */
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		/**
		 * 存放实现了Ordered接口的BeanPostProcessor实例
		 */
		List<String> orderedPostProcessorNames = new ArrayList<>();
		/**
		 * 存放剩余的BeanPostProcessor实例
		 */
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			/**
			 * 实现了PriorityOrdered接口的话就获取实例存放到集合中
			 * 如果实例实现了MergedBeanDefinitionPostProcessor中存放到相应的集合中
			 */
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			/**
			 * 实现了Ordered接口的话就将beanName存放到相应集合中
			 */
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			/**
			 * 没有实现任何排序接口的话就将beanName存放到相应集合中
			 */
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		/**
		 * 升序排序
		 * 对实现了PriorityOrdered接口的BeanPostProcessor实例进行排序,然后注册到容器中
		 */
  		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		/**
		 * 遍历实现了Ordered接口的BeanPostProcessor的beanName
		 * 获取其实例添加到相应的集合中,如果实现了MergedBeanDefinitionPostProcessor则存放到相应的集合中
		 * 然后排序注册到容器中
		 */
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		/**
		 * 遍历剩余实现了BeanPostProcessor接口beanName
		 * 获取其实例添加到相应的集合中,如果实现了MergedBeanDefinitionPostProcessor则存放到相应的集合中
		 * 然后注册到容器中
		 */
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		/**
		 *  MergedBeanDefinitionPostProcessor排在最后
		 * 最后排序实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor
		 * 然后注册到容器中
		 */
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		// ApplicationListenerDetector放在所有BeanPostProcessor之后,注意ApplicationListenerDetector的equals()方法实现
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

三、postProcessBeanDefinitionRegistry()解析

1. 方法总览

在执行invokeBeanFactoryPostProcessors()方法的过程中,会获取Spring内部提供的ConfigurationClassPostProcessor,执行其中的postProcessBeanDefinitionRegistry()以及postProcessBeanFactory()方法;

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		int registryId = System.identityHashCode(registry);
		if (this.registriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
		}
		if (this.factoriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + registry);
		}
		this.registriesPostProcessed.add(registryId);

		// 解析配置类
		processConfigBeanDefinitions(registry);
}

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();

		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			// 找配置类,什么是配置类?
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				//BeanDefinitionHolder顾明思义就是对BeanDefinition的持有,作用是根据名称或者别名持有beanDefination,承载了name和BeanDefination的映射信息
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
			return;
		}

		// Sort by previously determined @Order value, if applicable
		// 通过@Order可以排序,升序排序,order越小越靠前
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// Detect any custom bean name generation strategy supplied through the enclosing application context
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				// BeanNameGenerator,bean名字生成器
				// 可以预先往单例池中添加一个beanName为CONFIGURATION_BEAN_NAME_GENERATOR的BeanNameGenerator类型的bean
				// 用来作为bean名字生成器,生成扫描得到的Bean和import导入进来的Bean的beanName
				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();
		}

		//上面已经找到配置类了,接下来就是去解析配置类,所以这里会构造一个配置类的解析器
		// Parse each @Configuration class
		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());

		// 递归解析配置类,有可能通过解析一个配置类,得到了其他的配置类,比如扫描和Import
		do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");

			// 解析配置类,会把每个BeanDefinitionHolder首先封装为ConfigurationClass
			// 在这个过程中会进行扫描、导入等步骤,从而会找到其他的ConfigurationClass
			// 解析配置类的结果是什么?
			parser.parse(candidates);  // AppConfig.class--->BeanDefinition
			parser.validate();

			//由于解析配置类有可能会得到其它配置类,这里获取到的是目前为止所有的配置类,而且这些配置类是被解析过了的,但并不表示整个Spring容器只有这些配置类
			//例如解析AppConfig.class后,会得到其它的一些配置类
			// configClasses相当于就是解析之后的结果
			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			// 把所有的ConfigurationClass加载成BeanDefinition,通常情况下一个配置类会对应一个BeanDefinition,不过也有可能一个配置类对应多个BeanDefinition
			// 比如一个配置类中有多个加了@Bean注解的方法,会对应多个BeanDefination,一个配置类配置了@ImportResource,基本也会得到多个BeanDefintion
			this.reader.loadBeanDefinitions(configClasses);

			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			// candidates中存的是BeanDefinition,configClasses中存的是ConfigurationClass
			candidates.clear();

			// 如果发现BeanDefinition增加了,则有可能增加了配置类
			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);

						// 检查多出来的BeanDefinition是不是配置类,需不需要解析
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
		while (!candidates.isEmpty());

		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
		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();
		}
}

2. 处理流程

1. 从BeanFactory中,获取已经添加到Bean工厂中的BeanDefination

这里获取到的通常是在容器启动过程中Spring添加到BeanFactory中的BeanDefination,以及通过ApplicationContext的register()方法注册的类对应的BeanDefination;

2. 找配置类

2.1. 获取BeanDefination对应的类上面的注解的元数据,AnnotationMetadata表示某个类的注解信息;

2.2. 判断这个类上面有没有加@Configuration注解,进一步确定当前的类是不是配置类;

那什么样的类才算是配置类呢?这是才确定配置类的关键,符号以下条件的都会被判断为是配置类:

 ① 加了@Configuration注解,并且proxyBeanMethods不为false(为true或为null)时,就是full配置类;

 ② 加了@Configuration注解,并且proxyBeanMethods为false时,是lite配置类;

 ③ 没有加@Configuration注解,但是只要存在@Component、@ComponentScan、@Import、     @ImportResource四个中的一个,就是lite配置类;

 ④没有加@Configuration注解,只要存在加了@Bean注解的方法,就是lite配置类;

3.解析配置类

配置类思维脑图ProcessOn Mindmap

3.1. 首先会把类的元信息和beanName封装为ConfigurationClass;

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
	// 把类的元信息和beanName封装为ConfigurationClass
	processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

3.2. 处理配置类,配置类解析过后,最终会将解析过的配置类放到configurationClasses这个map中;

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
	// 条件注解,就是看有没有类上是否有@Conditional注解,如果有,则进行条件匹配
	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
	}
	ConfigurationClass existingClass = this.configurationClasses.get(configClass);
	if (existingClass != null) {
		if (configClass.isImported()) {
			// OrderService导入了AccountService,UserService也导入了AccountService,就会符合这个条件
			if (existingClass.isImported()) {
					existingClass.mergeImportedBy(configClass);
			}
			// Otherwise ignore new imported config class; existing non-imported class overrides it.
			return;
		}
		else {
			// Explicit bean definition found, probably replacing an import.
			// Let's remove the old one and go with the new one.
			this.configurationClasses.remove(configClass);
			this.knownSuperclasses.values().removeIf(configClass::equals);
		}
	}

	// Recursively process the configuration class and its superclass hierarchy.(递归处理配置类及其超类层次结构)
	SourceClass sourceClass = asSourceClass(configClass, filter);
	do {
		//有可能配置类还有父类,所以这里会有一个循环处理
		sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
	}
	while (sourceClass != null);

	// ConfigurationClass重写了equals方法,只要两个ConfigurationClass对应的className相等就可以
	this.configurationClasses.put(configClass, configClass);
}

3.3 如果配置类上有@Component注解,就要进一步判断加了@Component注解的配置类,有没有内部类,如果有,则判断内部类是不是配置类,如果是,就要解析内部类;

/**
 * 这样配置最终也会被Spring解析为配置类
 */
@Component
public class AppConfig implements AppInterface {


  // 内部类
  class  User{

 	 @Bean
 	 public  UserService userService(){
 	 	return new UserService();
	 }


  }

}

3.4. 如果配置类上加了@PropertySource注解,读取注解中指定的配置文件,将文件中的内容解析出来,放到environment中,例如@PropertySource("spring.properties");

3.5. 如果配置类上加了@ComponentScan注解,Spring就会进行扫描,得到的BeanDefinition会注册到Spring容器中,并且会检查扫描出来的BeanDefinition是不是配置类并进行解析;

说明:从定义来看,@Configuration 注解本质上还是@Component,因此,<context:component-scan/> 或者 @ComponentScan都能处理@Configuration注解的类;

3.6. 如果配置类上加了@Import()注解,解析注解中导入的类,那就要分情况了:

① 如果import的类实现了ImportSelector接口,将这个类实例化出来,又会分为两种情况:

 如果这个实例是DeferredImportSelector类型的,表示推迟的ImportSelector,它会在当前这一批配置类都解析完了之后执行;

public void parse(Set<BeanDefinitionHolder> configCandidates) {
	for (BeanDefinitionHolder holder : configCandidates) {
		BeanDefinition bd = holder.getBeanDefinition();
		try {
			// 解析BeanDefinition所对应的类
			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);
		}
	}

	// 处理deferredImportSelectors,表示当前所有配置类解析完了之后才执行
	// deferredImportSelector表示推迟的ImportSelector,正常的ImportSelector是在解析配置类的过程中执行的
	this.deferredImportSelectorHandler.process();
}

 如果这个实例不是DeferredImportSelector类型的,就会执行selectImports()方法,处理它返回的   类,这些返回的类会被当认为是导入进来的类,进而继续调用processImports()方法;

② 如果import的类实现了ImportBeanDefinitionRegistrar接口,将这个类实例化出来,然后将实例作为属性添加到configClass里面;

③ 如果导入的类是普通类,那就把它当做配置类来解析;

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
		Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
		boolean checkForCircularImports) {

	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) {
				// 如果import的类实现了ImportSelector接口
				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);
					}
					// 如果import的是DeferredImportSelector,表示推迟导入
					if (selector instanceof DeferredImportSelector) {
						this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
					} else {
						// 如果import的是普通的ImportSelector
						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
						// 继续处理selectImports()所返回的类,这些返回的类被认为是导入进来的类,
						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
						processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
					}
				}
				// 如果import的类实现了ImportBeanDefinitionRegistrar接口
				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 =
							ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
									this.environment, this.resourceLoader, this.registry);
					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
				}
				// 如果import的类就是普通的类,就把import进来的类当做配置类
				else {
					// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
					// process it as an @Configuration class
					this.importStack.registerImport(
							currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
					// 注意,在asConfigClass方法中,不仅会将candidate生成一个ConfigurationClass,还会记录一下candidate是被哪个类导入的importedBy
					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();
		}
	}
}

3.7. 如果配置类上加了ImportResource()注解,则获取注解中资源,将资源加入到当前配置类的属性中,此处仅仅是把注解内容解析出来,然后作为属性添加到configClass里面去,还并不是它真正的执行时机

一个通用的结论:

@PropertySource()用于导入.properties属性配置文件;

@ImportResource()用于导入.xml的Bean信息的配置文件;

3.8. 将配置类中加了@Bean注解的方法找到并记录,但这里并没有真正处理@Bean;

3.9. 解析配置类所实现的接口中有没有default的方法上是加了@Bean的,但并没有真正处理@Bean;

3.10. 如果当前配置类还有父类,将父类返回继续处理父类;

@Nullable
protected final SourceClass doProcessConfigurationClass(
		ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
		throws IOException {

	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
		// Recursively process any member (nested) classes first
		// 处理内部类
		// 在解析一个配置类时,如果类上有@Component,则会判断内部类是不是lite配置类并进行解析,并且会记录为被导入的
		processMemberClasses(configClass, sourceClass, filter);
	}

	// Process any @PropertySource annotations(处理@PropertySource注解)
	//如果配置类上加了@PropertySource,读取@PropertySource("spring.properties")中指定的配置文件,将文件中的内容解析出来,放到environment中
	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");
		}
	}

	// Process any @ComponentScan annotations(处理@ComponentScan注解)
	// 会进行扫描,得到的BeanDefinition会注册到Spring容器中,并且会检查是不是配置类并进行解析
	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
			// 这里就会进行扫描,得到的BeanDefinition会注册到Spring容器中
			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();
				}
				// 检查扫描出来的BeanDefinition是不是配置类(full和lite)
				if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
					parse(bdCand.getBeanClassName(), holder.getBeanName());
				}
			}
		}
	}

	// Process any @Import annotations(处理@Import注解)
	// getImports(sourceClass)会拿到@Import导入的类
	// 如果导入的是普通类,那么会直接把它当做配置类来解析
	// 如果导入的是普通ImportSelector,那么会将返回的类再次调用processImports()
	// 如果导入的是特殊ImportSelector,DeferredImportSelector,那么暂时不会处理,会在解析完所有当前这轮配置类后进行导入,将返回的类再次调用processImports()
	// 如果导入的是ImportBeanDefinitionRegistrar,那么暂时不会处理,会在解析完所有当前这轮配置类后,将配置类解析成为BeanDefinition之后进行调用
	processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

	// Process any @ImportResource annotations
	//获取注解中资源
	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) {
			// 显然它还支持${}这种方式去环境变量里取值的,比如spring-beans-${profie}.xml等
			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
			//将资源加入到当前配置类的属性中,此处仅仅是把注解解析出来,然后作为属性添加到configClass里面去,还并不是它真正的执行时机
			configClass.addImportedResource(resolvedResource, readerClass);
		}
	}

	// Process individual @Bean methods
	// 将配置类中加了@Bean注解的方法找到并记录,但并没有真正处理@Bean,即并没有真正地去解析加了@Bean注解的方法并生成BeanDefination,只是暂时找出来
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

	// Process default methods on interfaces
	// 解析配置类所实现的接口中有没有default的方法上是加了@Bean的,但并没有真正处理@Bean,只是暂时找出来
	processInterfaces(configClass, sourceClass);

	// Process superclass, if any
	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;
}

4. 针对解析过的配置类去加载BeanDefinition

4.1. 根据解析过的配置类去生成对应的BeanDefinition

回到processConfigBeanDefinitions()这个方法,由于执行parser.parse(candidates)解析配置类,

有可能会得到其它配置类,而所有的这些配置类中,如果有@Bean注解的方法、或者加了@ImportResource注解、或者是实现了ImportBeanDefinitionRegistrar接口的,在解析配置类的时候,只是把它们作为配置类的属性存储起来,还没有真正的处理,到this.reader.loadBeanDefinitions(configClasses)这一步才会真正的处理,生成BeanDefinition;

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;
	}

	if (configClass.isImported()) {
		// 将被导入的类生成BeanDefinition并注册到Spring容器中
		// @Component的内部类,@Import所导入的类都是被导入的类
		registerBeanDefinitionForImportedConfigurationClass(configClass);
	}

	// @Bean生成BeanDefinition并注册
	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		loadBeanDefinitionsForBeanMethod(beanMethod);
	}

	// 处理@ImportResource("spring.xml")
	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

	// 处理ImportBeanDefinitionRegistrar,调用registerBeanDefinitions()方法
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

4.2.  基于上述 4.1. 如果有新的BeanDefinition生成,还需要去判断是不是配置类、去解析,所以,这也是会出现do ...while循环的原因;

do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");

			// 解析配置类,会把每个BeanDefinitionHolder首先封装为ConfigurationClass
			// 在这个过程中会进行扫描、导入等步骤,从而会找到其他的ConfigurationClass
			// 解析配置类的结果是什么?
			parser.parse(candidates);  // AppConfig.class--->BeanDefinition
			parser.validate();

			//由于解析配置类有可能会得到其它配置类,这里获取到的是目前为止所有的配置类,而且这些配置类是被解析过了的,但并不表示整个Spring容器只有这些配置类
			//例如解析AppConfig.class后,会得到其它的一些配置类
			// configClasses相当于就是解析之后的结果
			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			// 针对所有解析过的ConfigurationClass,去加载BeanDefinition,通常情况下一个配置类会对应一个BeanDefinition,不过也有可能一个配置类对应多个BeanDefinition
			// 比如一个配置类中有多个加了@Bean注解的方法,会对应多个BeanDefination,一个配置类配置了@ImportResource,基本也会得到多个BeanDefintion
			//比如在下面这行代码执行之前,AppConfig1,是没有被解析过的,在这里才会被解析到,并且会生成BeanDefination,所以这里有可能又会得到一些新的BeanDefination
			this.reader.loadBeanDefinitions(configClasses);

			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			// candidates中存的是BeanDefinition,configClasses中存的是ConfigurationClass
			candidates.clear();

			// 如果发现BeanDefinition增加了,则有可能增加了配置类
			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);

						// 检查多出来的BeanDefinition是不是配置类,需不需要解析
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
	}
	while (!candidates.isEmpty());

四、关于@Configuration注解

1. 生成代理类

执行完BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法后,紧接着会执行postProcessBeanFactory()方法,在postProcessBeanFactory()方法中会为加了Configuration注解的配置类,生成代理类,注意:只有是full配置类时,才会为其生成代理类;

/**
 * Prepare the Configuration classes for servicing bean requests at runtime
 * by replacing them with CGLIB-enhanced subclasses.
 */
@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)) {
		// BeanDefinitionRegistryPostProcessor hook apparently not supported...
		// Simply call processConfigurationClasses lazily at this point then.
		processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
	}

	// 增强配置类,代理加了Configuration注解的配置类
	enhanceConfigurationClasses(beanFactory);

	beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();

		// 遍历,找出配置类
		for (String beanName : beanFactory.getBeanDefinitionNames()) {
			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
			Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
			AnnotationMetadata annotationMetadata = null;
			MethodMetadata methodMetadata = null;
			if (beanDef instanceof AnnotatedBeanDefinition) {
				AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
				annotationMetadata = annotatedBeanDefinition.getMetadata();
				methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
			}
			if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
				// Configuration class (full or lite) or a configuration-derived @Bean method
				// -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
				// or component class without @Bean methods.
				AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;

				// 没有加载类就去加载
				if (!abd.hasBeanClass()) {
					boolean liteConfigurationCandidateWithoutBeanMethods =
							(ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
								annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
					if (!liteConfigurationCandidateWithoutBeanMethods) {
						try {
							abd.resolveBeanClass(this.beanClassLoader);
						}
						catch (Throwable ex) {
							throw new IllegalStateException(
									"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
						}
					}
				}
			}
			if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
				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);
			}
		}
		if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
			// nothing to enhance -> return immediately
			enhanceConfigClasses.end();
			return;
		}

		// 生成代理类,并设置到BeanDefinition中,针对的是full配置类
		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
		for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
			AbstractBeanDefinition beanDef = entry.getValue();
			// If a @Configuration class gets proxied, always proxy the target class
			beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			// Set enhanced subclass of the user-specified bean class
			Class<?> configClass = beanDef.getBeanClass();  // Appconfig
			// 生成代理类
			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()));
				}
				//将当前配置类对应的BeanDefination对象的beanClass属性,设置成代理类
				//所以当根据这些BeanDefination创建Bean的时候,生成出来的是代理对象
				beanDef.setBeanClass(enhancedClass);
			}
		}
		enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
}

2. 代理类的作用

由于生成代理类后,当前配置类对应的BeanDefination对象中的beanClass属性会被设置为代理类,所以当根据这些BeanDefination创建Bean的时候,创建出来的就是代理对象了,那么在执行代理对象中的方法的时候(比如,加了@Bean注解的方法),就有可能执行的是代理逻辑了,那代理逻辑解决的问题是什么?

① 如果代理对象正在执行的方法就是当前正在创建的Bean的工厂方法,那就直接执行对应的方法得到对象作为Bean,什么意思呢?例如,Spring在创建OrderService类型的Bean的时候会在创建Bean实例(即createBeanInstance())这一步,处理@Bean对应的BeanDefinition,那么就会调用orderService()方法实例化OrderService对象,并且会记录当前正在调用的factoryMethod(也就是orderService()),由于此时的factoryBean是代理对象,所以会执行代理逻辑;调用orderService()方法实例化OrderService对象如下:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
		@Nullable Object factoryBean, final Method factoryMethod, Object... args) {

	try {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				ReflectionUtils.makeAccessible(factoryMethod);
				return null;
			});
		}
		else {
			ReflectionUtils.makeAccessible(factoryMethod);
		}

		Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
		try {
			currentlyInvokedFactoryMethod.set(factoryMethod);
			// factoryBean就是AppConfig的代理对象(如果加了@Configuration)
			// factoryMethod就是@Bean修饰的方法
			//如果factoryBean是代理对象,就会走代理逻辑
			Object result = factoryMethod.invoke(factoryBean, args);
			if (result == null) {
				result = new NullBean();
			}
				return result;
			}
		finally {
			if (priorInvokedFactoryMethod != null) {
				currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
			}
			else {
				currentlyInvokedFactoryMethod.remove();
			}
		}
	}
	catch (IllegalArgumentException ex) {
		throw new BeanInstantiationException(factoryMethod,
				"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
				"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
	}
	catch (IllegalAccessException ex) {
		throw new BeanInstantiationException(factoryMethod,
				"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
	}
	catch (InvocationTargetException ex) {
		String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
		if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
					((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
			msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
					"declaring the factory method as static for independence from its containing instance. " + msg;
		}
		throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
	}
}

代理逻辑如下:

public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
					MethodProxy cglibMethodProxy) throws Throwable {
			// enhancedConfigInstance是代理对象
			ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
			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;
				}
			}

			// To handle the case of an inter-bean method reference, we must explicitly check the
			// container for already cached instances.

			// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
			// proxy that intercepts calls to getObject() and returns any cached bean instance.
			// This ensures that the semantics of calling a FactoryBean from within @Bean methods
			// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
			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
					return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
				}
			}

			// 如果代理对象正在执行的方法就是当前正在创建Bean的工厂方法,那就直接执行对应的方法得到对象作为Bean
			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()));
				}
				// 注意这里传入的是代理对象,相当于在执行父类的方法,注意和Spring事务做区分
				return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
			}

			// 如果代理对象正在执行的方法不是正在创建Bean的方法,那就直接根据方法的名字去Spring容器中获取
			return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}

② 如果代理对象正在执行的方法不是正在创建的Bean的工厂方法,那就直接根据方法的名字去Spring容器中获取,这样可以保证@Bean方法的单例;上述①②情况代码示例如下:

@Configuration
public class AppConfig {

// 这里的orderService()方法会调三次,还有一次是Spring启动,创建OrderService类型的Bean的时候会调

    @Bean
	public UserService userService() {
		System.out.println(orderService());
		System.out.println(orderService());
		return new UserService();
	}


	@Bean
	public OrderService orderService(){
		return new OrderService();
	}

}

3. 总结

@Bean之间的方法调用是怎么保证单例的?( @Configuration加与不加的区别是什么?)

1.如果希望@Bean的方法返回是对象是单例 需要在类上面加上@Configuration;

2.Spring 会在invokeBeanFactoryPostProcessor 中,通过内置BeanFactoryPostProcessor会生成CGLib动态代理对象;

3.当@Bean方法进行互调时, 则会通过CGLIB进行增强,通过调用的方法名作为Bean的名称去ioc容器中获取,进而保证了@Bean方法的单例;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring之配置类源码深度解析 的相关文章

随机推荐