IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring中Bean定义的注册流程 -> 正文阅读

[Java知识库]Spring中Bean定义的注册流程

目录

一、前言

二、Bean定义的注册流程

1、注册流程

2、SpringApplication组件

2.1、run()核心逻辑

2.2、refresh(ApplicationContext applicationContext)

3、AbstractApplicationContext组件

3.1、refresh()逻辑

3.2、invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)

4、PostProcessorRegistrationDelegate组件

4.2、invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)逻辑

5、BeanDefinitionRegistryPostProcessor接口组件

6、ConfigurationClassPostProcessor组件

7、ConfigurationClassParser 组件

8、ClassPathBeanDefinitionScanner组件

9、BeanDefinitionReaderUtils工具类

10、DefaultListableBeanFactory容器工厂组件


一、前言

? ? 读源码的直接好处就是面试,对拿高薪有帮助。还有就是可以巩固你对JDK知识的灵活运用,因为Spring就是用Java写的(不懂就cop在源码中搜索一下查看别人是怎么写的),更高的追求就是学习其中的设计思想以便向高级工程师、架构师方向发展。但是许许多多的童鞋也许在大学那段时间被高级语言虐成狗,更何谈源码。相信有一小部分的童鞋还是可以的,只不过没有找到正确的打开方式。再次提醒下,大学一定要打牢基础,读读设计模式,然后读读源码。

? ? Spring的优秀之处很多,因其良好的封装、优秀的设计、面向接口编程、灵活使用设计模式、反射机制、Java读取XML方式等优点,而深受数不胜数的开发者喜爱。

二、Bean定义的注册流程

1、注册流程

? ? 总的来说组件有委托类后置处理器解析器包扫描器资源加载/读取器注册器BeanFactory等组件,Spring的Bean定义注册流程如此,Bean初始化也差不多,包括MyBatis的初始化也用到其中的部分设计。图中主要是组件内部调用以及组件间的调用流程,当然在调用前如果非静态操作的话都是要做如构造初始化的。

? ? 从上图可以看出ConfigurationClassPostProcessor这个后置处理器内部有个分支流程,会处理不同的Bean定义注册。右边的又是一个大的处理@Controller、@RestController、@Service、@Component等注解的Bean;左边的流程就较短一些,主要处理@Configuration的@Bean标志的Bean定义注册。

?注:可选择编辑,然后复制为图像。

2、SpringApplication组件

2.1、run()核心逻辑

	/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * 运行 Spring 应用程序,创建并刷新一个新的 ApplicationContext。
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 */
	public ConfigurableApplicationContext run(String... args) {
		//System.out.println("SpringApplication99999999999999999999999999");
		// 秒表,用于记录启动时间;记录每个任务的时间,最后会输出每个任务的总费时
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		// spring应用上下文,也就是我们所说的spring根容器,配置应用上下文,
		// 会根据class路径下的类初始化配置合适的应用上下文,比如是普通的spring应用(非web应用),还是web应用上下文。
		ConfigurableApplicationContext context = null;
		// 自定义SpringApplication启动错误的回调接口
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		// 设置jdk系统属性java.awt.headless,默认情况为true即开启;
		// 更多java.awt.headless信息大家可以去查阅资料,这不是本文重点
		configureHeadlessProperty();
		// 获取启动时监听器
		//此行代码的作用是从 /META-INF/spring.factories 文件中反射获取对应的 SpringApplicationRunListener实例:
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// 触发启动事件,相应的监听器会被调用
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			//紧接着调用 configureEnvironment(...)配置环境信息与激活的Profiles
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);
			//打印Logo:此处logo可以自定义,只需编写 banner.txt 在resources下即可。
			Banner printedBanner = printBanner(environment);
			//创建上下文:也是根据 webApplicationType字段决定创建哪种上下文对象,由于是SERVLET,所以此处会实例化
			//返回AnnotationConfigServletWebServerApplicationContext

			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);

			/**
			 * 创建完上下文之后,紧接着调用prepareContext(...) 填充上下文属性,将environment添加到上下文中、
			 * 上下文后置处理postProcessApplicationContext()、依次调用所有得ApplicationContextInitializer实例
			 * (构造方法中解析得initializers,上下文初始化之后,最先可以访问上下文的是initializers,
			 * 所以我们可以在Dubbo看到类似的扩展)。
			 *
			 *
			 * */
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

2.2、refresh(ApplicationContext applicationContext)

	/**
	 * Refresh the underlying {@link ApplicationContext}.刷新基础 ApplicationContext。
	 * @param applicationContext the application context to refresh
	 */
	protected void refresh(ApplicationContext applicationContext) {
		Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
		((AbstractApplicationContext) applicationContext).refresh();
	}

这里将applicationContext做了强制类型转换为AbstractApplicationContext类型,调用refresh()进入下一个组件逻辑处理。

3、AbstractApplicationContext组件

3.1、refresh()逻辑

	// Spring-framework初始化入口
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// 1.为应用上下文的刷新做准备--设置时间、记录刷新日志、初始化属性源中的占位符
			// (事实上什么都没做)和验证必要的属性等
			// Prepare this context for refreshing.
			prepareRefresh();

			// 2.让子类刷新内部的bean factory
			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 3.为上下文准备bean factory
			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

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

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// 5.调用应用上下文中作为bean注册的工厂处理器
				// 999520Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// 6.注册拦截创建bean的bean处理器
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// 7.初始化消息源
				// Initialize message source for this context.
				initMessageSource();

				// 8.初始化事件广播
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// 9.初始化特定上下文子类中的其它bean
				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// 10.注册监听器bean
				// Check for listener beans and register them.
				registerListeners();

				// 11.实例化所有的单例bean
				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// 12.发布相应的事件
				// 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();
			}
		}
	}

其中会内部调用invokeBeanFactoryPostProcessors(beanFactory);方法,调用应用上下文中作为bean注册的工厂处理器

3.2、invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

    }

可见它委托给PostProcessorRegistrationDelegate的一个静态方法去处理了。

4、PostProcessorRegistrationDelegate组件

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

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

			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();


			// 首先,调用实现 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor。
			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);
			// 111
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// 接下来,调用实现 Orded 的 BeanDefinitionRegistryPostProcessor。
			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);
			// 999520
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			// 最后,调用所有其他 BeanDefinitionRegistryPostProcessor,直到没有其他的出现为止。
			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();
			}

			
			// 现在,调用目前处理的所有处理器的 postProcessBeanFactory 回调。
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			// 调用注册到上下文实例的工厂处理器。
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		// 不要在这里初始化 FactoryBeans: 我们需要保留所有常规 bean 的未初始化状态,以便让 bean 工厂后处理程序应用到它们!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);


		// 在实现 PriorityOrded、 Ororder 和其他优先级的 BeanFactoryPostProcessor 之间分离。
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// 已在上述第一阶段处理
			}
			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);
			}
		}

		// 首先,调用实现 PriorityOrdered 的 BeanFactoryPostProcessor。
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		//接下来,调用实现 Ordered 的 BeanFactoryPostProcessor。
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 最后,调用所有其他 BeanFactoryPostProcessor。
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		//清除缓存的合并 bean 定义,因为后期处理可能已经修改了原始元数据,例如在值中替换占位符..。
		beanFactory.clearMetadataCache();
	}

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)调用这个方法继续往下走

4.2、invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)逻辑

	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
					.tag("postProcessor", postProcessor::toString);
			// 999520ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()
			postProcessor.postProcessBeanDefinitionRegistry(registry);
			postProcessBeanDefRegistry.end();
		}
	}

这里遍历Bean定义注册后置处理器类型的处理器,调用postProcessor.postProcessBeanDefinitionRegistry(registry)继续跟进

5、BeanDefinitionRegistryPostProcessor接口组件

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

它是一个接口,将交由它的实现类去处理,Bean注册定义初始化一般交由ConfigurationClassPostProcessor这个类去处理

6、ConfigurationClassPostProcessor组件

	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)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

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

	
		// 如果适用,按先前确定的@Order 值排序
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

	
		// 检测通过封闭的应用程序上下文提供的任何自定义 bean 名称生成策略
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

		// Parse each @Configuration class解析每个@Configuration 类
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
			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
			// 阅读模型并根据其内容创建 bean 定义
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			// 加载bean定义,即注册
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses); // 将已经加载解析的configClasses添加到alreadyParsed集合
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

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


		// 将 Import Registry 注册为 bean 以支持 Import Aware@Configuration 类
		if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
			// 在外部提供的 MetadataReaderFactory 中清除缓存; 这是共享缓存的禁用操作,
			// 因为它将被 ApplicationContext 清除。
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

parser.parse(candidates); 进入解析逻辑,在里面就会将@RestController、@Service、@Component等注解的Bean定义进行注册。解析完成后在下面一点的this.reader.loadBeanDefinitions(configClasses);开起对@Configuration中配置的Bean进行注册。由于这个逻辑比较简单,另一个逻辑后面的一部分其实也包括它了,感兴趣的读者自己去研究研究。

7、ConfigurationClassParser 组件

	/**
	 * 通过从源类中读取注释、成员和方法应用处理并构建完整的 ConfigurationClass。
	 * 当发现相关源时,可以多次调用此方法。
	 */
	@Nullable
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {

		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// 首先递归地处理任何成员(嵌套)类
			processMemberClasses(configClass, sourceClass, filter);
		}

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

		// 处理任何@ComponentScan(这个注解已经集成在@SpringBootApplication里)注释
		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) {
				
				// 该配置类使用@ComponentScan-> 注释,并立即执行扫描
				// admin模块在这里扫描出了6个如LoginConfig、MyBatisPlusConfig、CeaMUserServiceImpl等等
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// 检查扫描的定义集中是否有进一步的配置类,如果需要,可以递归地进行解析
				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());
					}
				}
			}
		}

		// 处理任何@Import 注释
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

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

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

		// 处理接口上的默认方法
		processInterfaces(configClass, sourceClass);

		// 处理超类(如果有的话)
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// 发现超类,返回其注释元数据和递归
				return sourceClass.getSuperClass();
			}
		}

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

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());调用组件扫描解析器解析处理。

这是解析后的?

8、ClassPathBeanDefinitionScanner组件

	/**
	 * 在指定的基本包中执行扫描,返回已注册的 bean 定义。换句话说就是已经注册了Bean
	 *
	 * 这个方法不会注册一个注释配置处理器,而是将这个任务留给调用者。
	 */
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
			// 999520它在(findCandidateComponents(basePackage))这里读到了
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					// LoginConfig
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					// LoginConfig
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					// LoginConfig
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					// 999520@Controller、@RestController、@Service、@Component等的注册
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

? ? 其中findCandidateComponents(basePackage)是.class文件资源加载读取的逻辑,调用ClassPathScanningCandidateComponentProvider组件的scanCandidateComponents(String basePackage)方法将读取到的资源封装成ScannedGenericBeanDefinition再添加到集合进行返回。这个方法内部对传过来的b包名进行拼接处理,传到getResourcePatternResolver().getResources(packageSearchPath)处理将Bean的class文件数据读取出来,里面还有一小部分逻辑,涉及到类加载器之类知识,感兴趣读者自行研究。

? ? 最后调用registerBeanDefinition(definitionHolder, this.registry);进入注册逻辑

9、BeanDefinitionReaderUtils工具类

	/**
	 * 向给定的 bean 工厂注册给定的 bean 定义。
	 */
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// 在主名称下注册 bean 定义。
		String beanName = definitionHolder.getBeanName();
		// 999520注册Bean,一般调用的是DefaultListableBeanFactory
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.注册 bean 名称的别名(如果有的话)。
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

这里逻辑不多,调用registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());这个方法将注册工作交给注册机去处理

10、DefaultListableBeanFactory容器工厂组件

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					// LoginConfig注册,一般的Bean走这里
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
		else if (isConfigurationFrozen()) {
			clearByTypeCache();
		}
	}

上一步的逻辑会BeanDefinitionRegistry接口,一般是交给它的实现类DefaultListableBeanFactory默认工厂容器类去处理,将Bean的定义存放到它的beanDefinitionMap结构的成员变量字段里面去。在此分享一个个人理解,成员变量就好像数据库,只是没有持久化。也可能正是因为这些理念才有了Redis数据库。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:27:03  更:2022-10-08 20:27:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 7:06:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码