当前位置: 首页 > article >正文

Spring beanFactoryPostProcessor

项目结构和代码

@Component
public class CustomerBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("CustomerBeanFactoryPostProcessor.postProcessBeanFactory");
    }
}
@Component
public class CustomerBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("CustomerBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry");
        AbstractBeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(NotComponentService.class).getBeanDefinition();
        beanDefinitionRegistry.registerBeanDefinition("notComponentService", definition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("CustomerBeanDefinitionRegistryPostProcessor.postProcessBeanFactory");
    }
}
@Service
public class HelloService {
}


@Service
public class UserService {
}


public class NotComponentService {
}
@ComponentScan
public class DddApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DddApplication.class);
    }

}


 

beanFactory 初始化流程

 构造器

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

	private final AnnotatedBeanDefinitionReader reader;

	private final ClassPathBeanDefinitionScanner scanner;


	public AnnotationConfigApplicationContext() {
		StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
		this.reader = new AnnotatedBeanDefinitionReader(this);
		createAnnotatedBeanDefReader.end();
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	
	
	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}
}

this()

首先调用父类构造器创建 beanFactory

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

	private final DefaultListableBeanFactory beanFactory;


	/**
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}
}

创建 AnnotatedBeanDefinitionReader

	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(this.registry)

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

		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

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

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

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

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

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

		return beanDefs;
	}


	private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(beanName, definition);
		return new BeanDefinitionHolder(definition, beanName);
	}

该方法的逻辑是向 beanFactory 添加五个 postProcessor

 此时无参构造已经执行完成,该构造一共做了三件事情

  1. 调用父类 GenericApplicationContext 的无参构造,创建  DefaultListableBeanFactory
  2. 创建 AnnotatedBeanDefinitionReader,添加五个 postProcessor的beanDefinition 到 beanFactory
  3. 创建 ClassPathBeanDefinitionScanner

register()

register(componentClasses) 的作用就是调用 AnnotatedBeanDefinitionReader.register() 将启动类注册到 beanDefinition

 

beanFactory refresh()

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

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

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

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

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

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

prepareBeanFactory()

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		if (!shouldIgnoreSpel) {
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		}
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
		}
	}

向 beanFactory 添加了两个 beanPostProcessor

添加四个组件

添加默认的 enviroment 组件

invokeBeanFactoryPostProcessors()

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// WARNING: Although it may appear that the body of this method can be easily
		// refactored to avoid the use of multiple loops and multiple lists, the use
		// of multiple lists and multiple passes over the names of processors is
		// intentional. We must ensure that we honor the contracts for PriorityOrdered
		// and Ordered processors. Specifically, we must NOT cause processors to be
		// instantiated (via getBean() invocations) or registered in the ApplicationContext
		// in the wrong order.
		//
		// Before submitting a pull request (PR) to change this method, please review the
		// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
		// to ensure that your proposal does not result in a breaking change:
		// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the bean factory post-processors apply to them!
			// Separate between BeanDefinitionRegistryPostProcessors that implement
			// PriorityOrdered, Ordered, and the rest.
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		// 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<>(orderedPostProcessorNames.size());
		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<>(nonOrderedPostProcessorNames.size());
		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

ConfigurationClassPostProcessor是一个BeanFactoryPostProcessor,用于处理一些配置信息和注解扫描,并且该处理器执行的时候有优先级顺序,优先执行PriorityOrdered,然后执行Ordered,最后执行默认没有优先级的处理器。

并且ConfigurationClassPostProcessor 是 spring框架中最重要的BeanFactoryPostProcessor,也是最重要的内置组件之一

作用:

  1. 对于候选配置类使用CGLIB Enhancer增强
  2. 解析处理@PropertySource 注解
  3. 解析@ComponentScan注解,扫描@Configuration、@Service、@Controller、@Repository和@Component注解并注册BeanDefinition
  4. 解析@Import注解,然后进行实例化,并执行ImportBeanDefinitionRegistrar的registerBeanDefinitions逻辑,或者ImportSelector的selectImports逻辑
  5. 解析@ImportResource注解,并加载相关配置信息
  6. 解析方法级别@Bean注解并将返回值注册成BeanDefinition
  7. 注册ImportRegistry到容器中,用于处理ImportAware

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors

org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	// 候选配置类定义列表
	List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
	// 获取容器中所有bean定义的名字
	String[] candidateNames = registry.getBeanDefinitionNames();
	// 循环名字
	for (String beanName : candidateNames) {
		// 获取bean定义
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
			// 省略...
		}
		// 查看bean是否是ConfigurationClass
		else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
			// 加入到候选配置类定义列表
			configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
		}
	}

	// 没有@Configuration的bean就返回
	if (configCandidates.isEmpty()) {
		return;
	}

	// 省略排序,beanName生成规则,环境变量等...

	// 构造一个配置类解析器,用来把bean定义的重要信息提取转化为ConfigurationClass
	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 {
		// 核心解析流程,重要!
        // 其实就是把类上面的特殊注解解析出来,最终封装成 BeanDefinition 注册到工厂
		parser.parse(candidates);
		parser.validate();

		// 获取解析器中解析出的配置类ConfigurationClass:parser.getConfigurationClasses()
		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());
		}
		// 读取ConfigurationClass获取衍生bean定义并注册到容器
        // 这里是去真正的注册!刚刚在解析 @Import、@Bean、@Import 等注解的时候,
        // 并没实际创建 BeanDefinition 并注册,而是将数据暂存起来
		this.reader.loadBeanDefinitions(configClasses);
		// 加入已解析配置类
		alreadyParsed.addAll(configClasses);
		// 清空候选配置类定义列表
		candidates.clear();
		// 如果容器中bean定义有新增
        // 这样做主要是防止有些 Bean 没有注册
		if (registry.getBeanDefinitionCount() > candidateNames.length) {
			/** 查找出新增的配置类bean定义 start **/
			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));
					}
				}
			}
			/**查找出新增的配置类bean定义 end , 最终新的配置bean定义加入到候选配置类定义列表 **/
			// 覆盖所有beanName,为下一次判断是否有新增
			candidateNames = newCandidateNames;
			
		}
	}
	while (!candidates.isEmpty()); // 只要候候选配置类定义列表不为空就一直循环下去

	// 省略...
}

上面的代码比较长,但流程很清晰,总结一下

  1. 查找spring容器中的配置类bean定义,存储候选列表
  2. 使用解析器,解析候选列表中的配置类bean定义,根据配置的扫描范围把相关的类都解析为ConfigurationClass对象(其中@CommpentScan下扫描的类直接注册bean定义)
  3. 使用读取器,读取上一步解析出的新未解析ConfigurationClass,注册相关bean定义
  4. 清空候选列表
  5. 继续查询spring容器,如果有新增的配置类bean定义,读取加入候选列表,跳转回第2步

 

上文ConfigurationClassPostProcessor对parser具体使用主要有三处

  • 初始化构造parser,传入了BeanDefinitionRegistry等构造传参数
  • 调用parse方法解析bean定义集合
  • 通过getConfigurationClasses方法获取解析结果configurationClasses

ConfigurationClassParser中一个属性configurationClasses,用来存放解析出来的结果

class ConfigurationClassParser {
  private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = new LinkedHashMap<>();
}

解析(parse)的重点责任就是根据传入的参数(bean定义列表)转化为Map<ConfigurationClass, ConfigurationClass>,下面重点分析分析方法:parse方法:

Parser#parse()

org.springframework.context.annotation.ConfigurationClassParser#parse() 

public void parse(Set<BeanDefinitionHolder> configCandidates) {
	// 循环
	for (BeanDefinitionHolder holder : configCandidates) {
		// 获取bean定义
		BeanDefinition bd = holder.getBeanDefinition();
		try {
			// 根据bean定义的类型走不通参数的重载parse方法
            // 扫描注解得到的 BeanDefinition
			if (bd instanceof AnnotatedBeanDefinition) {
				parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
			}
			else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                // 非扫描注解得到的 BeanDefinition
				parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
			}
			else {
				parse(bd.getBeanClassName(), holder.getBeanName());
			}
		}
		// 省略catch...
	}
     // 处理延迟加载的 importSelect,优先使用本项目的bean
	this.deferredImportSelectorHandler.process();
}

org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass 

protected void processConfigurationClass(ConfigurationClass configClass)  {
    // 根据注解信息判断是不是跳过解析
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
        return;
    }

    // 处理 Imported 的情况,就是当前这个注解类有没有被别的类 import
    ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    if (existingClass != null) {
        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);
    do {
        // 处理配置类
        sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    }
    while (sourceClass != null);

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

又是一个循环,调用doProcessConfigurationClass方法,如果有返回值,递归调用doProcessConfigurationClass,看spring的注释说递归解析配置类和他的父类,所以这代码的意思就是解析配置类,如果有父类再解析父类,如果父类有父类再一直解析下去。

最后this.configurationClasses.put(configClass, configClass);就是把上一步根据bean定义生成的ConfigurationClass对象存入解析的结果map:configurationClasses,实际上,对解析结果的添加只有这一处代码

如果单单看到这里,parser的功能就是把传入的多个bean定义循环转换为ConfigurationClass并存入解析结果中,相当于传入多少bean定义就转换多少ConfigurationClass对象

单parse方法的功能远不止如此,重点在doProcessConfigurationClass方法

doProcessConfigurationClass

org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

protected final SourceClass doProcessConfigurationClass(
		ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
		throws IOException {
    // 1.内部类  这一步看看有没有内部类
	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
		processMemberClasses(configClass, sourceClass, filter);
	}

	// 2.@PropertySource 这一步解析@PropertySource注解,更改配置文件位置时会使用,一般使用默认位置,不咋更改
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), PropertySources.class,
			org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			processPropertySource(propertySource);
		}
		// 省略...
	}

	// 3.@ComponentScan 这一步就很重要了,解析@ComponentScan注解
    // 此处或扫描到 @ComponentScan 注解包下面的所有加了 @Component、@Service 等注解的类
    // 注意的是,每扫描到一个符合条件的类,都要进行递归扫描,重新调用 doProcessConfigurationClass() 方法
	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) {
			// 这里扫描出来所有 @Component,并且把扫描的出来的普通 bean 放到 bdMap 当中
			Set<BeanDefinitionHolder> scannedBeanDefinitions =
					this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
			// 检查扫描的定义集是否有任何进一步的配置类,并在需要时进行递归解析
            // 检查扫描出来的类当中是否还有 configuration
			for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
				BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
				if (bdCand == null) {
					// 获取bean定义
					bdCand = holder.getBeanDefinition();
				}
				//判断是不是配置类
				if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
					// 检查扫描出来的配置类有没有配置类,进行再次解析,递归调用
					parse(bdCand.getBeanClassName(), holder.getBeanName());
				}
			}
		}
	}

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

	// 5.@ImportResource解析@ImportResource解析
    // 这里只是去解析配置文件的位置添加到配置类的 importedResources 中,没有进行扫描处理
	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 解析带有@Bean注解的方法,加入到configClass的beanMethods属性中
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

	// 6.接口@Bean 解析实现的接口中带有@Bean注解的默认方法,加入到configClass的beanMethods属性中
	processInterfaces(configClass, sourceClass);

	// 7.父类 如果有父类返回父类,以继续解析
	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();
		}
	}

	// 没有父类,解析结束
	return null;
}

这个方法很长,主要包含以下几个功能

  • 解析内部类
  • 解析@PropertySource注解
  • 解析@ComponentScan注解,扫描指定包下的所有@Component类,直接注册bean定义至spring,并递归解析
  • 解析@Import注解
  • 解析@ImportResource注解
  • 解析@Bean
  • 解析实现接口中的@Bean
  • 返回父类

所以doProcessConfigurationClass这一步的重点工作就是扫描某个配置类的注解,根据注解功能找到指定扫描范围的类,递归解析(调用parse或processConfigurationClass方法)

比如@ComponentScan就是扫描到basePackages指定路径下的类,然后通过递归调用parse解析这些类,@Import通过value属性指定的类,递归调用processConfigurationClass解析

重点这个递归,有了它就可以实现一个bean定义解析出多个ConfigurationClass对象

这里有个特例,@ComponentScan扫描的类会被直接注册到spring容器

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

也就是说如果一个类有@Component注解,processMemberClasses内部会解析当前类的内部类,如果是配置类,则会递归调用processConfigurationClass去解析这个内部类

private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
	// 获取所有内部类
	Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
	if (!memberClasses.isEmpty()) {
		// 候选列表
		List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
		for (SourceClass memberClass : memberClasses) {
			// 如果是配置类,加入候选
			if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
					!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
				candidates.add(memberClass);
			}
		}
		OrderComparator.sort(candidates);
		// 循环候选列表
		for (SourceClass candidate : candidates) {
			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();
				}
			}
		}
	}
}

解析@ComponentScan
Set<BeanDefinitionHolder> scannedBeanDefinitions =
                    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

componentScanParser内部有个scaner(扫描器),扫描@Component注解的类,包括子注解@Configuration@Service等(这过程还会直接把扫描到的类注册bean定义)

org.springframework.context.annotation.ComponentScanAnnotationParser#parse 

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    // Spring 自己 new 的一个 ClassPathBeanDefinitionScanner 进行扫描!这个类见到很多次了
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                                                                                componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

    // 下面这一堆都是在配置扫描策略...
    
    Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
    boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
    // 设置扫描器的 BeanName 生成器
    scanner.setBeanNameGenerator(useInheritedGenerator ?
                                 this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass));

    // 设置 componentScan 的代理模式
    ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
        scanner.setScopedProxyMode(scopedProxyMode);
    } else {
        Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
        scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    }

    // 设置扫描器的资源模式
    scanner.setResourcePattern(componentScan.getString("resourcePattern"));

    // 看看 componentScan 注解是否设置了 includeFilters 属性
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addIncludeFilter(typeFilter);
        }
    }

    // 看看 componentScan 注解是否设置了 excludeFilters 属性
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addExcludeFilter(typeFilter);
        }
    }

    // 	看看 componentScan 注解是否设置了 lazyInit 属性
    boolean lazyInit = componentScan.getBoolean("lazyInit");
    if (lazyInit) {
        scanner.getBeanDefinitionDefaults().setLazyInit(true);
    }

    // 此集合放的是扫描的路径
    Set<String> basePackages = new LinkedHashSet<>();
    // 获取componentScan注解的basePackages属性
    String[] basePackagesArray = componentScan.getStringArray("basePackages");
    for (String pkg : basePackagesArray) {
        String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                                                               ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        Collections.addAll(basePackages, tokenized);
    }
    for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
        basePackages.add(ClassUtils.getPackageName(clazz));
    }
    if (basePackages.isEmpty()) {
        basePackages.add(ClassUtils.getPackageName(declaringClass));
    }

    scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
        @Override
        protected boolean matchClassName(String className) {
            return declaringClass.equals(className);
        }
    });
    // 开始扫描
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}

org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    // 存储创建出的 BeanDefinitionHolder
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (String basePackage : basePackages) {
        // 依次扫描每个包中的相关注解,创建获取到所有的 BeanDefinition
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            // 生成 Bean 的名称
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            if (checkCandidate(beanName, candidate)) {
                // 包装成 BeanDefinitionHolder
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                // 创建代理
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                 // 注册到上下文工厂
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

扫描的核心是 findCandidateComponents 方法,这个方法就是寻找到 @Component 和 @Component 的衍生注解的类。

org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents 

回到 org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

循环判断扫描到的类是否是ConfigurationClass,如果是则递归解析

解析@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

参数getImports方法获取到了当前配置类所有@Import注解指定的类集合,然后进入processImports

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

	// 省略...
	
	// 循环所有@Import指定的类
	for (SourceClass candidate : importCandidates) {
		// 如果这个类实现了ImportSelector,即导入多个类
		if (candidate.isAssignable(ImportSelector.class)) {
			// 实例化这个导入的ImportSelector类
			ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
							this.environment, this.resourceLoader, this.registry);
							
			// 省略一些过滤...
			
			// 如果是延迟导入,交给deferredImportSelectorHandler处理
			if (selector instanceof DeferredImportSelector) {
				this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
			}
			// 普通的多个导入
			else {
				// 找到导入的多个类
				String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
				Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
				// 递归调用当前方法
				processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
			}
		}
		// 如果这个类实现了ImportBeanDefinitionRegistrar
		else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
			// 实例化这个ImportBeanDefinitionRegistrar类
			ImportBeanDefinitionRegistrar registrar =
							ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
									this.environment, this.resourceLoader, this.registry);
			// 加入该类到当前配置类解析对象ConfigurationClass的importBeanDefinitionRegistrars列表属性中
			configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
		}
		// 排除上面两种情况,这个类就是个普通类
		else {
			// 省略...
			// 递归解析这个类
			processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
		}
	}
		
}

这里涉及的内容较多,主要分几种情况

  • 如果导入的就是普通类 直接递归解析这个类
  • 如果导入的类实现了ImportBeanDefinitionRegistrar(导入的bean定义注册器) 直接实例化这个类,并加入到当前解析配置类的importBeanDefinitionRegistrars(列表)属性中,以便后续调用其registerBeanDefinitions方法
  • 如果导入的是实现了ImportSelector的普通类(多类导入) 直接实例化这个类,循环selectImports方法放回的多个类,递归调用processImports
  • 如果导入的是实现了DeferredImportSelector的特殊ImportSelector类(延迟多类导入) 直接实例化这个类,委托给解析器内部的deferredImportSelectorHandler处理,deferredImportSelectorHandler内部把这个实例对象和当前解析类封装为DeferredImportSelectorHolder, 暂存入解析器内部的deferredImportSelectors属性 因为是延迟,所以这里暂存了一下,并没有像普通ImportSelector那样循环递归解析processImports,而其真正的执行实际就是上文parse主方法最后的那一句this.deferredImportSelectorHandler.process(),而process方法内部依然是循环递归processImports方法,只不过延迟了,相当于所有的类被解析过才开始解析DeferredImportSelector导入的类

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

这里通过解析当前配置类@Bean方法,并将方法打包为BeanMethod存入配置类beanMethods属性中

总结Parser

基本上parser内部解析的重点方法都分析完了,总结一下,parser都干了什么?

  • parser作为一个解析器,根据传入的配置类解析出多个ConfigurationClass对象

  • 配置类实际上是一个树形结构,他的子节点包含@ComponentScan扫描到的配置类,@Import引入的普通类等

  • 而spring中这个树结构的根节点一般就是用户定义的主启动类

  • parser通过递归解析完成整个树的解析(解析成多个ConfigurationClass对象),并把解析结果存入parser内部configurationClasses属性

  • parser解析某个配置类节点过程中 会把其@Bean方法加入ConfigurationClass对象的属性beanMethods列表中 会把@Import注解引入的ImportBeanDefinitionRegistrar加入ConfigurationClass对象的属性importBeanDefinitionRegistrars列表中 会把@Import注解引入的DeferredImportSelector加入到解析器内部的属性deferredImportSelectors列表中,延迟到所有节点解析完成后再统一解析

  • 在解析某配置类的@ComponentScan注解时,扫描到的类会同时注册bean定义至spring容器

所以最终结果是把根配置类下的整个树扫描,生成多个ConfigurationClass对象,同时@ComponentScan扫描到的配置类会直接注册bean定义

最后画个图梳理整个解析过程

image.png

DeferredImportSelector只不过是延迟导入,从整个解析过程来看最终结果与@Import一样

Reader

相比于parser,reader的任务轻松多了,主要任务就是把parser解析出的ConfigurationClass集合读取并转换为bean定义,并最终注册到spring容器

回到 org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
		for (ConfigurationClass configClass : configurationModel) {
			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
		}
	}
private void loadBeanDefinitionsForConfigurationClass(
		ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

	// 省略的

	// 注册被Import引入的类,标识ConfigurationClass.isImported==true
	if (configClass.isImported()) {
		registerBeanDefinitionForImportedConfigurationClass(configClass);
	}
	// 注册@Bean的工厂方法,存储在ConfigurationClass.beanMethods属性中
	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		loadBeanDefinitionsForBeanMethod(beanMethod);
	}

	// ImportedResource(忽略)
	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
	// 执行ImportBeanDefinitionRegistrar实现注册用户自定义bean定义,存储在ConfigurationClass.importBeanDefinitionRegistrars属性中
	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

Parser注册了@ComponentScan扫描的bean定义,而Reader主要注册了这几个bean定义

  • 通过@Import引入的(标识ConfigurationClass.isImported==true)
  • @Bean的工厂方法(存储在ConfigurationClass.beanMethods属性中)
  • 执行ImportBeanDefinitionRegistrar实现注册用户自定义bean定义(存储在ConfigurationClass.importBeanDefinitionRegistrars属性中)

这么一看Reader反而成了捡漏的了...,就是把Parser没注册的bean定义都注册上

其中loadBeanDefinitionsFromRegistrars这步就是执行ImportBeanDefinitionRegistrar实现的registerBeanDefinitions方法,即用户自定义注册bean常用的@Import+ImportBeanDefinitionRegistrar模式的实际执行时机

image.png

回到 org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()

可以看到我没自定义的 bean已经注册进容器了

  Ordered  BeanDefinitionRegistryPostProcessors

all other BeanDefinitionRegistryPostProcessors

执行自定义的 BeanDefinitionRegistryPostProcessor,并向容器中注册一个 beanDefition

beanDefinitionRegisterPostProcesso.rpostProcessBeanFactory

接下来按照优先级依次执行  BeanFactoryPostProcessor

 


http://www.kler.cn/a/375099.html

相关文章:

  • git clone必须使用sudo否则失败 git推送错误想再次编辑和推送
  • 亚远景-SO 21434标准下的汽车网络安全:风险评估与管理的关键实践
  • Git 的基本概念和使用
  • Asp.Net FrameWork 4.7.2 WebAPI 使用WebSocket协议
  • 2.Couchbase 的增量查询优化
  • WPF自定义窗口 输入验证不生效
  • Redis 线程控制 问题
  • 在linux中是如何运行一个应用程序的?
  • (七)JavaWeb后端开发1——Maven
  • 大语言模型驱动的跨域属性级情感分析——论文阅读笔记
  • 创造tips的秘籍——PHP回调后门
  • Redis 实战 问题
  • 【Sublime Text】格式化Json和XML
  • 线代的几何意义(一)——向量,坐标,矩阵
  • thinkphp和vue基于Workerman搭建Websocket服务实现用户实时聊天,完整前后端源码demo及数据表sql
  • Docker部署jenkins容器时,允许jenkins容器内部控制宿主机上的docker
  • 正向解析,反向解析
  • CSS3新增长度单位(二)
  • 从比亚迪超越特斯拉,看颠覆全球市场的中国力量
  • 大语言模型微调方法详解【全量微调、PEFT、LoRA、Adapter】
  • Rust 力扣 - 2090. 半径为 k 的子数组平均值
  • 低压电容补偿不用时会有电流损耗吗?
  • Lampiao靶机入侵实战
  • 计算机考研,选择西安交通大学还是哈工大?
  • 吞吐量最高飙升20倍!破解强化学习训练部署难题
  • Java解析word中的表格或者文本