java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot注解@Import ConfigurationClassPostProcessor源码

SpringBoot注解@Import原理之关于ConfigurationClassPostProcessor源码解析

作者:谈谈1974

这篇文章主要介绍了SpringBoot注解@Import原理之关于ConfigurationClassPostProcessor源码解析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

1. @Import 介绍

1.1 @Import 的作用

Spring 中将一个普通类交给容器管理除了使用 @Bean@Component等注解再使用 @ComponentScan 扫描包之外,还可以使用 @Import 注解

@Import只能用在类或者其他注解上 ,该注解能够方便快速地实现把实例加入到 Spring 的 IOC 容器中,可用于导入第三方包

1.2 @Import 的使用方式

@Import 可以快速导入目标类,其主要有以下几种用法:

1.2.1 直接导入目标类

这种方式直接在@Import中指定 class 数组,Spring 会在启动过程把 @Import 中配置的 bean 直接导入到 Spring 容器中,其 beanName 为类的全限定名,使用方法如下:

@Import({ abc.class , abd.class... })
public class Config {
}
1.2.2 导入实现 ImportSelector 接口的类

ImportSelector是一个导入的选择器,可以通过这个接口的实现决定引入哪些配置。

@EnableAsync上通过@Import导入的 AsyncConfigurationSelector 为例,Spring 容器会在启动过程中实例化该选择器并调用其selectImports()方法。

AsyncConfigurationSelector#selectImports() 根据 @EnableAsync 中指定的模式选择对应的配置类,默认代理模式,则导入指定的 ProxyAsyncConfiguration配置类

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

	private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
			"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
			
	@Override
	@Nullable
	public String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return new String[] {ProxyAsyncConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
			default:
				return null;
		}
	}

}
1.2.3 导入实现 ImportBeanDefinitionRegistrar 接口的类

ImportBeanDefinitionRegistrar 是一个 bean 定义注册器,以 @EnableAspectJAutoProxy注解通过 @Import(AspectJAutoProxyRegistrar.class) 引入了注册类 AspectJAutoProxyRegistrar 为例,在框架启动过程中会回调其实现的接口方法 AspectJAutoProxyRegistrar#registerBeanDefinitions()方法将目标 bean 注册到容器中

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

2. @Import 注册目标类的流程

以下流程图以 @EnableAsync 注解使用 @Import 导入 AsyncConfigurationSelector 为例子,全流程展现了@Import 导入的类被解析为 BeanDefinition 并注册到 Spring 容器中过程,以及 @Async注解核心原理。

简单来说,整个过程总共分为以下几步:

2.1 配置解析类ConfigurationClassPostProcessor的注册

SpringApplication#run() 方法为框架启动的入口,启动过程中 prepareContext() 方法会为 Context 准备必要的组件,其中就包括 ConfigurationClassPostProcessor 的注册

public ConfigurableApplicationContext run(String... args) {
 	
 	......
 	
 	try {
 		ApplicationArguments applicationArguments = new DefaultApplicationArguments(
 				args);
 		ConfigurableEnvironment environment = prepareEnvironment(listeners,
 				applicationArguments);
 		configureIgnoreBeanInfo(environment);
 		Banner printedBanner = printBanner(environment);
 		context = createApplicationContext();
 		exceptionReporters = getSpringFactoriesInstances(
 				SpringBootExceptionReporter.class,
 				new Class[] { ConfigurableApplicationContext.class }, context);
 		prepareContext(context, environment, listeners, applicationArguments,
 				printedBanner);
 		refreshContext(context);
 		afterRefresh(context, applicationArguments);
 		stopWatch.stop();
 		
 	......
 	
 	return context;
 }

SpringApplication#prepareContext() 中会调用 SpringApplication#load() 将必要的组件加载进容器中,以下为 load() 方法实现,可以看到方法内部调用了 createBeanDefinitionLoader() 方法

protected void load(ApplicationContext context, Object[] sources) {
 	if (logger.isDebugEnabled()) {
 		logger.debug(
 				"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
 	}
 	BeanDefinitionLoader loader = createBeanDefinitionLoader(
 			getBeanDefinitionRegistry(context), sources);
 	if (this.beanNameGenerator != null) {
 		loader.setBeanNameGenerator(this.beanNameGenerator);
 	}
 	if (this.resourceLoader != null) {
 		loader.setResourceLoader(this.resourceLoader);
 	}
 	if (this.environment != null) {
 		loader.setEnvironment(this.environment);
 	}
 	loader.load();
 }

SpringApplication#createBeanDefinitionLoader() 会创建 BeanDefinition 的加载器,最终创建的对象为 BeanDefinitionLoader

protected BeanDefinitionLoader createBeanDefinitionLoader(
		BeanDefinitionRegistry registry, Object[] sources) {
	return new BeanDefinitionLoader(registry, sources);
}

BeanDefinitionLoader 的构造方法中会初始化一系列的组件,其中包括了 AnnotatedBeanDefinitionReader

BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
 	Assert.notNull(registry, "Registry must not be null");
 	Assert.notEmpty(sources, "Sources must not be empty");
 	this.sources = sources;
 	this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
 	this.xmlReader = new XmlBeanDefinitionReader(registry);
 	if (isGroovyPresent()) {
 		this.groovyReader = new GroovyBeanDefinitionReader(registry);
 	}
 	this.scanner = new ClassPathBeanDefinitionScanner(registry);
 	this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
 }

AnnotatedBeanDefinitionReader 的构造方法会通过工具类AnnotationConfigUtils#registerAnnotationConfigProcessors()注册注解配置的处理器

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
 	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
 	Assert.notNull(environment, "Environment must not be null");
 	this.registry = registry;
 	this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
 	AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
 }

AnnotationConfigUtils#registerAnnotationConfigProcessors() 方法会注册许多 Spring 必须的处理器,本文主要关注 ConfigurationClassPostProcessor 这个配置类的后置处理器,可以看到此时已经将其包装到 BeanDefinition中了

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
 		BeanDefinitionRegistry registry, @Nullable Object source) {
    ......

 	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

 	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
 		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
 		def.setSource(source);
 		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
 	}
    ......

 	return beanDefs;
 }

2.2 ConfigurationClassPostProcessor 解析配置类

Context 准备完毕,会调用 SpringAppliction#refreshContext() 方法,最终调用到著名的 AbstractApplicationContext#refresh() 方法。

该方法体内各个方法的作用可参考Spring启动流程源码解析,本文主要关注 invokeBeanFactoryPostProcessors()方法

public void refresh() throws BeansException, IllegalStateException {
 	synchronized (this.startupShutdownMonitor) {
 		// Prepare this context for refreshing.
 		prepareRefresh();

 		// Tell the subclass to refresh the internal bean factory.
 		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

 		// Prepare the bean factory for use in this context.
 		prepareBeanFactory(beanFactory);

 		try {
 			// Allows post-processing of the bean factory in context subclasses.
 			postProcessBeanFactory(beanFactory);

 			// Invoke factory processors registered as beans in the context.
 			invokeBeanFactoryPostProcessors(beanFactory);

 			// Register bean processors that intercept bean creation.
 			registerBeanPostProcessors(beanFactory);

 			// Initialize message source for this context.
 			initMessageSource();

 			// Initialize event multicaster for this context.
 			initApplicationEventMulticaster();

 			// Initialize other special beans in specific context subclasses.
 			onRefresh();

 			// Check for listener beans and register them.
 			registerListeners();

 			// Instantiate all remaining (non-lazy-init) singletons.
 			finishBeanFactoryInitialization(beanFactory);

 			// Last step: publish corresponding event.
 			finishRefresh();
 		}

 		......
 	}
 }

AbstractApplicationContext#invokeBeanFactoryPostProcessors()方法会调用 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() 方法,这个方法的源码如下,可以看到其主要做了以下几件事:

public static void invokeBeanFactoryPostProcessors(
 		ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
     
     ......
 	
 	// Do not initialize FactoryBeans here: We need to leave all regular beans
 	// uninitialized to let the bean factory post-processors apply to them!
 	String[] postProcessorNames =
 			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

 	// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
 	// Ordered, and the rest.
 	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
 	List<String> orderedPostProcessorNames = new ArrayList<>();
 	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
 	for (String ppName : postProcessorNames) {
 		if (processedBeans.contains(ppName)) {
 			// skip - already processed in first phase above
 		}
 		else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
 			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
 		}
 		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
 			orderedPostProcessorNames.add(ppName);
 		}
 		else {
 			nonOrderedPostProcessorNames.add(ppName);
 		}
 	}

 	// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
 	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
 	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

 	// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
 	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
 	for (String postProcessorName : orderedPostProcessorNames) {
 		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
 	}
 	sortPostProcessors(orderedPostProcessors, beanFactory);
 	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

 	// Finally, invoke all other BeanFactoryPostProcessors.
 	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
 	for (String postProcessorName : nonOrderedPostProcessorNames) {
 		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
 	}
 	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

 	// Clear cached merged bean definitions since the post-processors might have
 	// modified the original metadata, e.g. replacing placeholders in values...
 	beanFactory.clearMetadataCache();
 }

ConfigurationClassPostProcessor 已经完成注册,且实现了 BeanFactoryPostProcessor 接口,则经过步骤 2 ConfigurationClassPostProcessor#postProcessBeanFactory() 方法将被调用,可以看到方法内部核心其实是ConfigurationClassPostProcessor#processConfigBeanDefinitions() 方法

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

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

ConfigurationClassPostProcessor#processConfigBeanDefinitions() 方法,其内部比较重要的步骤如下:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

 	......
 	
 	// 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());
 	do {
 		parser.parse(candidates);
 		parser.validate();

 		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());
 		}
 		this.reader.loadBeanDefinitions(configClasses);
 		alreadyParsed.addAll(configClasses);

 		candidates.clear();
 		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);
 					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();
 	}
 }

ConfigurationClassParser#parse() 方法是解析配置类的核心入口,其最终调用到了 ConfigurationClassParser#processConfigurationClass()方法。

这个方法主要处理逻辑是调用 doProcessConfigurationClass()解析配置类,并将解析得到的 Bean 缓存在 Map 集合 configurationClasses 中供后续注册使用

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
 	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
 		return;
 	}

 	ConfigurationClass existingClass = this.configurationClasses.get(configClass);
 	if (existingClass != null) {
 		if (configClass.isImported()) {
 			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);
 	do {
 		sourceClass = doProcessConfigurationClass(configClass, sourceClass);
 	}
 	while (sourceClass != null);

 	this.configurationClasses.put(configClass, configClass);
 }

ConfigurationClassParser#doProcessConfigurationClass() 是解析配置的核心方法,其主要的处理步骤如下,本文主要关注 processImports() 处理 @Import 注解引入 Bean 的流程

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
 		throws IOException {

 	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
 		// Recursively process any member (nested) classes first
 		processMemberClasses(configClass, sourceClass);
 	}

 	// Process any @PropertySource annotations
 	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
 	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());
 				}
 			}
 		}
 	}

 	// Process any @Import annotations
 	processImports(configClass, sourceClass, getImports(sourceClass), 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) {
 			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
 			configClass.addImportedResource(resolvedResource, readerClass);
 		}
 	}

 	// Process individual @Bean methods
 	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
 	for (MethodMetadata methodMetadata : beanMethods) {
 		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
 	}

 	// Process default methods on interfaces
 	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;
 }

ConfigurationClassParser#processImports() 方法主要处理 3 种类型的 Bean:

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
 		Collection<SourceClass> importCandidates, 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) {
 				if (candidate.isAssignable(ImportSelector.class)) {
 					// Candidate class is an ImportSelector -> delegate to it to determine imports
 					Class<?> candidateClass = candidate.loadClass();
 					ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
 					ParserStrategyUtils.invokeAwareMethods(
 							selector, this.environment, this.resourceLoader, this.registry);
 					if (selector instanceof DeferredImportSelector) {
 						this.deferredImportSelectorHandler.handle(
 								configClass, (DeferredImportSelector) selector);
 					}
 					else {
 						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
 						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
 						processImports(configClass, currentSourceClass, importSourceClasses, false);
 					}
 				}
 				else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
 					// Candidate class is an ImportBeanDefinitionRegistrar ->
 					// delegate to it to register additional bean definitions
 					Class<?> candidateClass = candidate.loadClass();
 					ImportBeanDefinitionRegistrar registrar =
 							BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
 					ParserStrategyUtils.invokeAwareMethods(
 							registrar, this.environment, this.resourceLoader, this.registry);
 					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
 				}
 				else {
 					// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
 					// process it as an @Configuration class
 					this.importStack.registerImport(
 							currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
 					processConfigurationClass(candidate.asConfigClass(configClass));
 				}
 			}
 		}
 		catch (BeanDefinitionStoreException ex) {
 			throw ex;
 		}
 		catch (Throwable ex) {
 			throw new BeanDefinitionStoreException(
 					"Failed to process import candidates for configuration class [" +
 					configClass.getMetadata().getClassName() + "]", ex);
 		}
 		finally {
 			this.importStack.pop();
 		}
 	}
 }

经过步骤5-7处理,引入的类都被解析完毕,接下来则会调用 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions() 将配置类中的解析出来的 Bean 注册到容器中

从代码来看,其实核心是 loadBeanDefinitionsForConfigurationClass() 方法完成注册工作,这里主要把需要注册的类分为了以下 4 类。

通过这个步骤,@EnableAsync 注解上经 @Import 导入的 AsyncConfigurationSelector 选择器选中的配置类 ProxyAsyncConfiguration 注册到了容器中,并且这个配置类内部配置的AsyncAnnotationBeanPostProcessor 也注册到了容器中

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()) {
 		registerBeanDefinitionForImportedConfigurationClass(configClass);
 	}
 	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
 		loadBeanDefinitionsForBeanMethod(beanMethod);
 	}

 	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
 	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
 }

2.3 BeanPostProcessor 后置处理器对象的优先创建

容器启动过程中AbstractApplicationContext#invokeBeanFactoryPostProcessors() 准备 Bean 工厂的后置处理器完毕,就需要调用 AbstractApplicationContext#registerBeanPostProcessors() 将 Bean 的后置处理器注册到容器中了。

这个过程通过 PostProcessorRegistrationDelegate.registerBeanPostProcessors() 方法完成,其流程与 Bean 工厂后置处理器的注册大致相同:

public static void registerBeanPostProcessors(
 		ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

 	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
     
     ......
 	
 	// Now, register all regular BeanPostProcessors.
 	List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
 	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.
 	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).
 	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
 }

此处着重分析beanFactory.getBean() Bean 工厂创建 BeanPostProcessor 对象的过程,追踪代码容易得知获取 Bean 调用到了 AbstractBeanFactory#doGetBean() 方法。

这个方法很长,本文主要分析流程主干,也就是 createBean() 抽象方法

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
 		@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        
        ......
 		
 		// Check if bean definition exists in this factory.
 		BeanFactory parentBeanFactory = getParentBeanFactory();
 		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 			// Not found -> check parent.
 			String nameToLookup = originalBeanName(name);
 			if (parentBeanFactory instanceof AbstractBeanFactory) {
 				return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 						nameToLookup, requiredType, args, typeCheckOnly);
 			}
 			else if (args != null) {
 				// Delegation to parent with explicit args.
 				return (T) parentBeanFactory.getBean(nameToLookup, args);
 			}
 			else if (requiredType != null) {
 				// No args -> delegate to standard getBean method.
 				return parentBeanFactory.getBean(nameToLookup, requiredType);
 			}
 			else {
 				return (T) parentBeanFactory.getBean(nameToLookup);
 			}
 		}

 		if (!typeCheckOnly) {
 			markBeanAsCreated(beanName);
 		}

 		try {
 			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 			checkMergedBeanDefinition(mbd, beanName, args);

 			// Guarantee initialization of beans that the current bean depends on.
 			String[] dependsOn = mbd.getDependsOn();
 			if (dependsOn != null) {
 				for (String dep : dependsOn) {
 					if (isDependent(beanName, dep)) {
 						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 								"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 					}
 					registerDependentBean(dep, beanName);
 					try {
 						getBean(dep);
 					}
 					catch (NoSuchBeanDefinitionException ex) {
 						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 								"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
 					}
 				}
 			}

 			// Create bean instance.
 			if (mbd.isSingleton()) {
 				sharedInstance = getSingleton(beanName, () -> {
 					try {
 						return createBean(beanName, mbd, args);
 					}
 					catch (BeansException ex) {
 						// Explicitly remove instance from singleton cache: It might have been put there
 						// eagerly by the creation process, to allow for circular reference resolution.
 						// Also remove any beans that received a temporary reference to the bean.
 						destroySingleton(beanName);
 						throw ex;
 					}
 				});
 				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 			}

 			else if (mbd.isPrototype()) {
 				// It's a prototype -> create a new instance.
 				Object prototypeInstance = null;
 				try {
 					beforePrototypeCreation(beanName);
 					prototypeInstance = createBean(beanName, mbd, args);
 				}
 				finally {
 					afterPrototypeCreation(beanName);
 				}
 				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
 			}

 			else {
 				String scopeName = mbd.getScope();
 				final Scope scope = this.scopes.get(scopeName);
 				if (scope == null) {
 					throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
 				}
 				try {
 					Object scopedInstance = scope.get(beanName, () -> {
 						beforePrototypeCreation(beanName);
 						try {
 							return createBean(beanName, mbd, args);
 						}
 						finally {
 							afterPrototypeCreation(beanName);
 						}
 					});
 					bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
 				}
 				catch (IllegalStateException ex) {
 					throw new BeanCreationException(beanName,
 							"Scope '" + scopeName + "' is not active for the current thread; consider " +
 							"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
 							ex);
 				}
 			}
 		}
 		catch (BeansException ex) {
 			cleanupAfterBeanCreationFailure(beanName);
 			throw ex;
 		}
 	}

 	......
 	
 	return (T) bean;
 }

AbstractAutowireCapableBeanFactory#createBean() 方法中会调用 doCreateBean() 方法去创建 Bean 对象

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
 		throws BeanCreationException {

 	if (logger.isTraceEnabled()) {
 		logger.trace("Creating instance of bean '" + beanName + "'");
 	}
 	RootBeanDefinition mbdToUse = mbd;

 	// Make sure bean class is actually resolved at this point, and
 	// clone the bean definition in case of a dynamically resolved Class
 	// which cannot be stored in the shared merged bean definition.
 	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
 	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
 		mbdToUse = new RootBeanDefinition(mbd);
 		mbdToUse.setBeanClass(resolvedClass);
 	}

 	// Prepare method overrides.
 	try {
 		mbdToUse.prepareMethodOverrides();
 	}
 	catch (BeanDefinitionValidationException ex) {
 		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
 				beanName, "Validation of method overrides failed", ex);
 	}

 	try {
 		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
 		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
 		if (bean != null) {
 			return bean;
 		}
 	}
 	catch (Throwable ex) {
 		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
 				"BeanPostProcessor before instantiation of bean failed", ex);
 	}

 	try {
 		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
 		if (logger.isTraceEnabled()) {
 			logger.trace("Finished creating instance of bean '" + beanName + "'");
 		}
 		return beanInstance;
 	}
 	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
 		// A previously detected exception with proper bean creation context already,
 		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
 		throw ex;
 	}
 	catch (Throwable ex) {
 		throw new BeanCreationException(
 				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
 	}
 }

AbstractAutowireCapableBeanFactory#doCreateBean() 方法中主要完成了以下工作,此处为了解决循环引用的问题,允许未创建完成的 Bean 对象提前暴露出来,主要是通过 Map 集合 earlySingletonObjects 缓存实现的

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
		throws BeanCreationException {

	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	......

	// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		if (logger.isTraceEnabled()) {
			logger.trace("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		populateBean(beanName, mbd, instanceWrapper);
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
			throw (BeanCreationException) ex;
		}
		else {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
		}
	}

	if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			}
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName,
							"Bean with name '" + beanName + "' has been injected into other beans [" +
							StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
							"] in its raw version as part of a circular reference, but has eventually been " +
							"wrapped. This means that said other beans do not use the final version of the " +
							"bean. This is often the result of over-eager type matching - consider using " +
							"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}

	// Register bean as disposable.
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
}

AbstractAutowireCapableBeanFactory#initializeBean() 方法会调用 invokeAwareMethods() 方法检查对象实现的接口,如果其实现了特定接口,则接口方法将被调用。

此处异步任务的后置处理器 AsyncAnnotationBeanPostProcessor#setBeanFactory() 方法将被调用

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

private void invokeAwareMethods(final String beanName, final Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}

AsyncAnnotationBeanPostProcessor#setBeanFactory() 方法可以看到其创建了异步任务切面 AsyncAnnotationAdvisor,该切面中包含了增强拦截器AnnotationAsyncExecutionInterceptor 和切入点AnnotationMatchingPointcut,将在后续创建 @Async 标注的 bean 时用于创建代理对象

后续@Async 异步任务代理对象的生成及其生效原理不再继续分析,读者根据流程图理解即可

 public void setBeanFactory(BeanFactory beanFactory) {
 	super.setBeanFactory(beanFactory);

 	AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
 	if (this.asyncAnnotationType != null) {
 		advisor.setAsyncAnnotationType(this.asyncAnnotationType);
 	}
 	advisor.setBeanFactory(beanFactory);
 	this.advisor = advisor;
 }

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文