Меч относится к исходному коду Spring (2)

Java

Это первая запись в блоге после Праздника Весны.Когда я думала об этом блоге, то хотелось бросить и подумать, писать ли что-то еще, ведь мой личный уровень все-таки ограничен. Куриц можно освоить, но Боюсь не понять детей, а писать блоги об анализе исходного кода слишком сложно. Это действительно отличается от обычных блогов. Я может и много написал, и не знаю, что пишу, но все же я должен проявлять настойчивость. С того дня, как я вступил в контакт с блогом, я очень восхищался этими великими богами, был готов поделиться и самоотверженно посвятил себя. Я также многому научился из этих блогов и постепенно превратился из нежного маленького цыпленка лысому цыпленку. , Больше всего восхищаюсь теми блогами об анализе исходного кода.Хотя я не могу их понять, я ясно могу прочитать любовь великих богов к технологиям, настойчивость в технологиях и преданность технологиям из блога. сохраняются в!

В предыдущем анализе исходного кода Spring мы проанализировали

	//根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少
	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		//调用无参构造函数,会先调用父类GenericApplicationContext的构造函数
		//父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory
		//本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefinitionScanner scanner
		//scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
		this();
		//把传入的类进行注册,这里有两个情况,
		//传入传统的配置类
		//传入bean(虽然一般没有人会这么做
		//看到后面会知道spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配置类
		//但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean
		register(annotatedClasses);
		//刷新
		refresh();
	}

Первые две строки кода в , оглядываясь назад, эти две строки кода в основном делят наш класс конфигурации и несколько встроенных постпроцессоров на два набора:

				//beanDefinitionMap是Map<String, BeanDefinition>,
				//这里就是把beanName作为key,beanDefinition作为value,推到map里面
				this.beanDefinitionMap.put(beanName, beanDefinition);

				//beanDefinitionNames就是一个List<String>,这里就是把beanName放到List中去
				this.beanDefinitionNames.add(beanName);

Сегодня разберем третью строчку кода, а именно:

		//刷新
		refresh();

Этот метод делает много вещей, давайте нажмем на этот метод:

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			//刷新预处理,和主流程关系不大,就是保存了容器的启动时间,启动标志等
			prepareRefresh();

			//DefaultListableBeanFactory
			// Tell the subclass to refresh the internal bean factory.
			//和主流程关系也不大,最终获得了DefaultListableBeanFactory,
			// DefaultListableBeanFactory实现了ConfigurableListableBeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//还是一些准备工作,添加了两个后置处理器:ApplicationContextAwareProcessor,ApplicationListenerDetector
			//还设置了 忽略自动装配 和 允许自动装配 的接口,如果不存在某个bean的时候,spring就自动注册singleton bean
			//还设置了bean表达式解析器 等
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//这是一个空方法
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//执行自定义的BeanFactoryProcessor和内置的BeanFactoryProcessor
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 注册BeanPostProcessor
				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();
			}

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

В нем много маленьких методов, наша цель сегодня — разобрать первые пять маленьких методов:

prepareRefresh

С точки зрения именования мы знаем, что этот метод в основном выполняет некоторую подготовительную работу перед обновлением, которая имеет мало общего с основным процессом, в основном сохраняет время запуска и флаг запуска контейнера.

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()

Связь между этим методом и основным процессом не очень большая, можно просто считать, что нужно просто вынуть beanFactory.

prepareBeanFactory

			//还是一些准备工作,添加了两个后置处理器:ApplicationContextAwareProcessor,ApplicationListenerDetector
			//还设置了 忽略自动装配 和 允许自动装配 的接口,如果不存在某个bean的时候,spring就自动注册singleton bean
			//还设置了bean表达式解析器 等
			prepareBeanFactory(beanFactory);

Этот код более важен, чем два предыдущих, нам нужно щелкнуть и внимательно посмотреть, что он сделал:

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());//设置类加载器

		//设置bean表达式解析器
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

		//属性编辑器支持
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		//添加一个后置处理器:ApplicationContextAwareProcessor,此后置处理处理器实现了BeanPostProcessor接口
		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 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.
		//添加一个后置处理器:ApplicationListenerDetector,此后置处理器实现了BeanPostProcessor接口
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (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()));
		}

		//如果没有注册过bean名称为XXX,spring就自己创建一个名称为XXX的singleton bean
		//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());
		}
	}

Основные операции следующие:

  1. установить загрузчик классов
  2. Парсер выражения bean-компонента установлен
  3. Добавлена ​​поддержка редактора свойств
  4. Добавлен постпроцессор: ApplicationContextAwareProcessor, реализующий интерфейс BeanPostProcessor.
  5. Установите некоторые интерфейсы, которые игнорируют автопроводку
  6. Настройте некоторые интерфейсы, позволяющие автоматическую сборку, и выполняйте операции назначения
  7. Когда в контейнере нет bean-компонента XX, помогите нам зарегистрировать одноэлементный bean-компонент, beanName которого равен XX.

postProcessBeanFactory(beanFactory)

				//这是一个空方法
				postProcessBeanFactory(beanFactory);

Это пустой метод, который может быть расширен Spring в будущем.

invokeBeanFactoryPostProcessors(beanFactory)

				//执行自定义的BeanFactoryProcessor和内置的BeanFactoryProcessor
				invokeBeanFactoryPostProcessors(beanFactory);

Код ключа наконец-то здесь.Можно сказать, что этот код на сегодняшний день самый важный и самый содержательный.Нам необходимо его проанализировать:

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

		//getBeanFactoryPostProcessors真是坑,第一次看到这里的时候,愣住了,总觉得获得的永远都是空的集合,掉入坑里,久久无法自拔
		//后来才知道spring允许我们手动添加BeanFactoryPostProcessor
		//即:annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX);
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

Давайте посмотрим на второй параметр первого маленького метода:

	public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
		return this.beanFactoryPostProcessors;
	}

Здесь я получил BeanFactoryPostProcessor.Когда я это увидел, я был ошеломлен.Через справочную функцию поиска IDEA я обнаружил, что эта коллекция всегда пуста, и нет никакого кода для добавления данных в эту коллекцию.Я не разобрался Позже я узнал, что мы можем вручную добавить постпроцессор извне, вместо того, чтобы отдавать его Spring для сканирования, а именно:

		AnnotationConfigApplicationContext annotationConfigApplicationContext =
				new AnnotationConfigApplicationContext(AppConfig.class);
		annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX);

Только так этот набор не будет пустым, но так делать никто не должен, конечно, может быть и я неуч.

Откроем метод invokeBeanFactoryPostProcessors:

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

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

		//beanFactory是DefaultListableBeanFactory,是BeanDefinitionRegistry的实现类,所以肯定满足if
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

			//regularPostProcessors 用来存放BeanFactoryPostProcessor,
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();

			//registryProcessors 用来存放BeanDefinitionRegistryPostProcessor
			//BeanDefinitionRegistryPostProcessor扩展了BeanFactoryPostProcessor
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			// 循环传进来的beanFactoryPostProcessors,正常情况下,beanFactoryPostProcessors肯定没有数据
			// 因为beanFactoryPostProcessors是获得手动添加的,而不是spring扫描的
			// 只有手动调用annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX)才会有数据
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				// 判断postProcessor是不是BeanDefinitionRegistryPostProcessor,因为BeanDefinitionRegistryPostProcessor
				// 扩展了BeanFactoryPostProcessor,所以这里先要判断是不是BeanDefinitionRegistryPostProcessor
				// 是的话,直接执行postProcessBeanDefinitionRegistry方法,然后把对象装到registryProcessors里面去
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}

				else {//不是的话,就装到regularPostProcessors
					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.
			//一个临时变量,用来装载BeanDefinitionRegistryPostProcessor
			//BeanDefinitionRegistry继承了PostProcessorBeanFactoryPostProcessor
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			// 获得实现BeanDefinitionRegistryPostProcessor接口的类的BeanName:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
			// 并且装入数组postProcessorNames,我理解一般情况下,只会找到一个
			// 这里又有一个坑,为什么我自己创建了一个实现BeanDefinitionRegistryPostProcessor接口的类,也打上了@Component注解
			// 配置类也加上了@Component注解,但是这里却没有拿到
			// 因为直到这一步,Spring还没有去扫描,扫描是在ConfigurationClassPostProcessor类中完成的,也就是下面的第一个
			// invokeBeanDefinitionRegistryPostProcessors方法
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//获得ConfigurationClassPostProcessor类,并且放到currentRegistryProcessors
					//ConfigurationClassPostProcessor是很重要的一个类,它实现了BeanDefinitionRegistryPostProcessor接口
					//BeanDefinitionRegistryPostProcessor接口又实现了BeanFactoryPostProcessor接口
					//ConfigurationClassPostProcessor是极其重要的类
					//里面执行了扫描Bean,Import,ImportResouce等各种操作
					//用来处理配置类(有两种情况 一种是传统意义上的配置类,一种是普通的bean)的各种逻辑
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					//把name放到processedBeans,后续会根据这个集合来判断处理器是否已经被执行过了
					processedBeans.add(ppName);
				}
			}

			//处理排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);

			//合并Processors,为什么要合并,因为registryProcessors是装载BeanDefinitionRegistryPostProcessor的
			//一开始的时候,spring只会执行BeanDefinitionRegistryPostProcessor独有的方法
			//而不会执行BeanDefinitionRegistryPostProcessor父类的方法,即BeanFactoryProcessor的方法
			//所以这里需要把处理器放入一个集合中,后续统一执行父类的方法
			registryProcessors.addAll(currentRegistryProcessors);

			//可以理解为执行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
			//Spring热插播的体现,像ConfigurationClassPostProcessor就相当于一个组件,Spring很多事情就是交给组件去管理
			//如果不想用这个组件,直接把注册组件的那一步去掉就可以
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

			//因为currentRegistryProcessors是一个临时变量,所以需要清除
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			// 再次根据BeanDefinitionRegistryPostProcessor获得BeanName,看这个BeanName是否已经被执行过了,有没有实现Ordered接口
			// 如果没有被执行过,也实现了Ordered接口的话,把对象推送到currentRegistryProcessors,名称推送到processedBeans
			// 如果没有实现Ordered接口的话,这里不把数据加到currentRegistryProcessors,processedBeans中,后续再做处理
			// 这里才可以获得我们定义的实现了BeanDefinitionRegistryPostProcessor的Bean
			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);

			//合并Processors
			registryProcessors.addAll(currentRegistryProcessors);

			//执行我们自定义的BeanDefinitionRegistryPostProcessor
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

			//清空临时变量
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			// 上面的代码是执行了实现了Ordered接口的BeanDefinitionRegistryPostProcessor,
			// 下面的代码就是执行没有实现Ordered接口的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);
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			//registryProcessors集合装载BeanDefinitionRegistryPostProcessor
			//上面的代码是执行子类独有的方法,这里需要再把父类的方法也执行一次
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

			//regularPostProcessors装载BeanFactoryPostProcessor,执行BeanFactoryPostProcessor的方法
			//但是regularPostProcessors一般情况下,是不会有数据的,只有在外面手动添加BeanFactoryPostProcessor,才会有数据
			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!
		//找到BeanFactoryPostProcessor实现类的BeanName数组
		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<>();
		//循环BeanName数组
		for (String ppName : postProcessorNames) {
			//如果这个Bean被执行过了,跳过
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			//如果实现了PriorityOrdered接口,加入到priorityOrderedPostProcessors
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			//如果实现了Ordered接口,加入到orderedPostProcessorNames
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			//如果既没有实现PriorityOrdered,也没有实现Ordered。加入到nonOrderedPostProcessorNames
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		//排序处理priorityOrderedPostProcessors,即实现了PriorityOrdered接口的BeanFactoryPostProcessor
		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//执行priorityOrderedPostProcessors
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		//执行实现了Ordered接口的BeanFactoryPostProcessor
		// 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);

		// 执行既没有实现PriorityOrdered接口,也没有实现Ordered接口的BeanFactoryPostProcessor
		// 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();
	}

Сначала определите, является ли beanFactory экземпляром BeanDefinitionRegistry, конечно, это так, а затем выполните следующие действия:

  1. Определяется набор и загружается BeanName.Позже на основе этого набора оценивается, был ли выполнен постпроцессор.

  2. Определены два списка: один — RegularPostProcessors, который используется для загрузки BeanFactoryPostProcessor, а другой — RegistrationProcessors, который используется для загрузки BeanDefinitionRegistryPostProcessor, в котором BeanDefinitionRegistryPostProcessor расширяет BeanFactoryPostProcessor. BeanDefinitionRegistryPostProcessor имеет два метода: один — уникальный метод postProcessBeanDefinitionRegistry, а другой — метод postProcessBeanFactory родительского класса.

  3. BeanFactoryPostProcessors, переданные через цикл, были объяснены выше.При нормальных обстоятельствах это всегда пусто.Только при ручном добавлении beanFactoryPostProcessors здесь будут данные. Мы предполагаем, что у beanFactoryPostProcessors есть данные, входим в цикл и определяем, является ли postProcessor BeanDefinitionRegistryPostProcessor, потому что BeanDefinitionRegistryPostProcessor расширяет BeanFactoryPostProcessor, поэтому здесь мы должны сначала определить, является ли он BeanDefinitionRegistryPostProcessor, если да, выполнить метод postProcessBeanDefinitionRegistry, а затем установить объект в RegistrationProcessors, в противном случае просто загружается в обычные постпроцессоры.

  4. Определена временная переменная: currentRegistryProcessors, которая используется для загрузки BeanDefinitionRegistryPostProcessor.

  5. getBeanNamesForType, как следует из названия, находит BeanNames в соответствии с типом. Здесь следует обратить внимание на то, где его найти. Если вы нажмете на этот метод, вы узнаете, что ищете beanDefinitionNames в цикле. будет часто встречаться в будущем. Здесь передается BeanDefinitionRegistryPostProcessor.class, который должен найти постпроцессор типа BeanDefinitionRegistryPostProcessor и назначить его postProcessorNames. При нормальных обстоятельствах будет найден только один — org.springframework.context.annotation.internalConfigurationAnnotationProcessor, то есть ConfigurationAnnotationProcessor. Этот постпроцессор был объяснен в предыдущем разделе и очень важен. Вот вопрос, почему я сам написал класс, реализовал интерфейс BeanDefinitionRegistryPostProcessor, и аннотировал его с помощью @Component, но у меня не получилось, потому что до этого шага Spring не завершил сканирование, а сканирование сделано в классе ConfigurationClassPostProcessor, то есть первый метод invokeBeanDefinitionRegistryPostProcessors ниже.

  6. Цикл postProcessorNames, который на самом деле является org.springframework.context.annotation.internalConfigurationAnnotationProcessor, чтобы определить, реализует ли этот постпроцессор интерфейс PriorityOrdered (ConfigurationAnnotationProcessor также реализует интерфейс PriorityOrdered), Если она реализована, добавьте ее во временную переменную currentRegistryProcessors, а затем поместите в обрабатываемые бины, указав, что постобработка выполнена. Конечно, это еще не решено, но скоро будет решено. . .

  7. Для сортировки PriorityOrdered — интерфейс сортировки, если он реализован, значит, постпроцессор в порядке, поэтому сортировка нужна. Конечно, в настоящее время существует только один постпроцессор, ConfigurationClassPostProcessor.

  8. Объедините currentRegistryProcessors в RegistryProcessors, зачем вам это нужно? Поскольку Spring будет выполнять только уникальный метод BeanDefinitionRegistryPostProcessor в начале и не будет выполнять метод родительского класса BeanDefinitionRegistryPostProcessor, то есть метод в интерфейсе BeanFactoryProcessor, необходимо поместить эти постпроцессоры в коллекцию, а затем равномерно выполнить интерфейс BeanFactoryProcessor. Конечно, в настоящее время существует только один постпроцессор, ConfigurationClassPostProcessor.

  9. Его можно понимать как выполнение метода postProcessBeanDefinitionRegistry в ConfigurationClassPostProcessor в currentRegistryProcessors, что является воплощением дизайнерской идеи Spring, отражающей идею горячей замены и разработки плагинов. Многие вещи в Spring передаются на обработку плагину.Этот постпроцессор эквивалентен плагину.Если вы не хотите его использовать,просто не добавляйте его. Этот метод особенно важен, и мы подробно обсудим его позже.

  10. Очистите currentRegistryProcessors, потому что currentRegistryProcessors является временной переменной и завершила текущую миссию, поэтому ее нужно очистить, естественно, она будет использоваться позже.

  11. Снова получите BeanName в соответствии с BeanDefinitionRegistryPostProcessor, а затем проверьте, был ли выполнен постпроцессор. Здесь мы можем получить постпроцессор, который мы определили и аннотировали с помощью @Component, т.к. Spring завершил сканирование, но здесь следует отметить, что, поскольку выше был выполнен ConfigurationClassPostProcessor, он хоть и может быть получен через getBeanNamesForType, но не будет добавлены в currentRegistryProcessors и обрабатываемые компоненты Beans.

  12. Ручная сортировка.

  13. Объедините процессоры по тем же причинам, что и выше.

  14. Выполните наш пользовательский BeanDefinitionRegistryPostProcessor.

  15. Очистить временные переменные.

  16. В приведенном выше методе выполняется только BeanDefinitionRegistryPostProcessor, реализующий интерфейс Ordered, здесь выполняется BeanDefinitionRegistryPostProcessor, не реализующий интерфейс Ordered.

  17. Вышеприведенный код предназначен для выполнения метода, уникального для подкласса.Здесь метод родительского класса необходимо выполнить снова.

  18. Для выполнения метода постпроцессора в регулярных постпроцессорах следует отметить, что при нормальных обстоятельствах в регулярных постпроцессорах не будет данных, только если снаружи вручную добавить BeanFactoryPostProcessor, данные будут.

  19. Найдите постпроцессор, который реализует BeanFactoryPostProcessor, и выполните методы в постпроцессоре. Это похоже на приведенную выше логику и не будет подробно объясняться.

Это основное, что делается в этом методе, можно сказать, более сложном. Но логика все еще относительно ясна.В шаге 9 я сказал, что есть метод, который будет объяснен подробно.Теперь давайте хорошенько посмотрим на то, что этот метод делает.

	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();//获得所有的BeanDefinition的Name,放入candidateNames数组

		//循环candidateNames数组
		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);//根据beanName获得BeanDefinition

			// 内部有两个标记位来标记是否已经处理过了
			// 这里会引发一连串知识盲点
			// 当我们注册配置类的时候,可以不加Configuration注解,直接使用Component ComponentScan Import ImportResource注解,称之为Lite配置类
			// 如果加了Configuration注解,就称之为Full配置类
			// 如果我们注册了Lite配置类,我们getBean这个配置类,会发现它就是原本的那个配置类
			// 如果我们注册了Full配置类,我们getBean这个配置类,会发现它已经不是原本那个配置类了,而是已经被cgilb代理的类了
			// 写一个A类,其中有一个构造方法,打印出“你好”
			// 再写一个配置类,里面有两个bean注解的方法
			// 其中一个方法new了A 类,并且返回A的对象,把此方法称之为getA
			// 第二个方法又调用了getA方法
			// 如果配置类是Lite配置类,会发现打印了两次“你好”,也就是说A类被new了两次
			// 如果配置类是Full配置类,会发现只打印了一次“你好”,也就是说A类只被new了一次,因为这个类被cgilb代理了,方法已经被改写
			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
					ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}

			//判断是否为配置类(有两种情况 一种是传统意义上的配置类,一种是普通的bean),
			//在这个方法内部,会做判断,这个配置类是Full配置类,还是Lite配置类,并且做上标记
			//满足条件,加入到configCandidates
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// 如果没有配置类,直接返回
		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
			return;
		}

		// Sort by previously determined @Order value, if applicable
		//处理排序
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// Detect any custom bean name generation strategy supplied through the enclosing application context
		SingletonBeanRegistry sbr = null;
		// DefaultListableBeanFactory最终会实现SingletonBeanRegistry接口,所以可以进入到这个if
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				//spring中可以修改默认的bean命名方式,这里就是看用户有没有自定义bean命名方式,虽然一般没有人会这么做
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

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

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

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			//解析配置类(传统意义上的配置类或者是普通bean,核心来了)
			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);//直到这一步才把Import的类,@Bean @ImportRosource 转换成BeanDefinition
			alreadyParsed.addAll(configClasses);//把configClasses加入到alreadyParsed,代表

			candidates.clear();
			//获得注册器里面BeanDefinition的数量 和 candidateNames进行比较
			//如果大于的话,说明有新的BeanDefinition注册进来了
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();//从注册器里面获得BeanDefinitionNames
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));//candidateNames转换set
				Set<String> alreadyParsedClasses = new HashSet<>();
				//循环alreadyParsed。把类名加入到alreadyParsedClasses
				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();
		}
	}
  1. Получите все BeanNames и поместите их в массив KandNames.
  2. Зациклить массив KandiNames, получить BeanDefinition в соответствии с beanName и определить, было ли обработано BeanDefinition.
  3. Определите, является ли это классом конфигурации, и если да. При добавлении в массив configCandidates при оценке он также будет помечать, принадлежит ли класс конфигурации к классу полной конфигурации или классу конфигурации Lite, что приведет к ряду слепых зон знаний: 3.1 Когда мы регистрируем класс конфигурации, мы можем напрямую использовать такие аннотации, как @Component @ComponentScan @Import @ImportResource без добавления аннотации @Configuration. Spring называет этот класс конфигурации классом конфигурации Lite. Если аннотация @Configuration добавлена, то вызов это класс полной конфигурации. 3.2 Если мы зарегистрируем класс конфигурации Lite, мы получим класс конфигурации Bean и обнаружим, что это исходный класс конфигурации.Если мы зарегистрируем класс конфигурации Full, мы обнаружим, что класс конфигурации getBean не является исходным класс конфигурации Это класс, который был проксирован cgilb. 3.3 Напишите класс A, у которого есть конструктор, распечатайте «Hello», а затем напишите класс конфигурации с двумя методами, аннотированными @bean, один из которых новый класс A и возвращает объект A, вызовите этот метод getA и второй метод вызывает метод getA. Если класс конфигурации является классом конфигурации Lite, вы обнаружите, что "Hello" печатается дважды, то есть класс A является новым дважды. Класс является классом полной конфигурации, и вы обнаружит, что "Hello" печатается только один раз, что означает, что класс A является новым только один раз, потому что этот класс проксируется cgilb, а метод был переписан. 3.4 Подробности смотрите в моем блоге:nuggets.capable/post/684490…Внутри есть подробная инструкция.
  4. Если класс конфигурации отсутствует, вернитесь напрямую.
  5. Ручная сортировка.
  6. Класс конфигурации синтаксического анализа может быть классом полной конфигурации или классом конфигурации Lite.Этот небольшой метод является ядром этого метода, который будет подробно объяснен позже.
  7. На шаге 6 регистрируются только некоторые bean-компоненты, такие как @Import @Bean и т. д., которые не зарегистрированы, и здесь они регистрируются единообразно.

Вот процесс разбора класса конфигурации:

	public void parse(Set<BeanDefinitionHolder> configCandidates) {
		this.deferredImportSelectors = new LinkedList<>();
		//循环传进来的配置类
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();//获得BeanDefinition
			try {
				//如果获得BeanDefinition是AnnotatedBeanDefinition的实例
				if (bd instanceof AnnotatedBeanDefinition) {
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				} else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			} catch (BeanDefinitionStoreException ex) {
				throw ex;
			} catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}

		//执行DeferredImportSelector
		processDeferredImportSelectors();
	}

Поскольку может быть несколько классов конфигурации, их необходимо обрабатывать в цикле. BeanDefinition нашего класса конфигурации является экземпляром AnnotatedBeanDefinition, поэтому он войдет первым, если:

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName));
	}
	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);
	}

Основное внимание уделяется методу doProcessConfigurationClass, который требует особого внимания Последняя строка кода поместит configClass в карту, которая будет использоваться на шаге 7 выше.

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

		//递归处理内部类,一般不会写内部类
		// Recursively process any member (nested) classes first
		processMemberClasses(configClass, sourceClass);

		// Process any @PropertySource annotations
		//处理@PropertySource注解,@PropertySource注解用来加载properties文件
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			} else {
				logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}

		// Process any @ComponentScan annotations
		//获得ComponentScan注解具体的内容,ComponentScan注解除了最常用的basePackage之外,还有includeFilters,excludeFilters等
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);

		//如果没有打上ComponentScan,或者被@Condition条件跳过,就不再进入这个if
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			//循环处理componentScans
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				//componentScan就是@ComponentScan上的具体内容,sourceClass.getMetadata().getClassName()就是配置类的名称
				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)) {
						//递归调用,因为可能组件类有被@Bean标记的方法,或者组件类本身也有ComponentScan等注解
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// Process any @Import annotations
		//处理@Import注解
		//@Import注解是spring中很重要的一个注解,Springboot大量应用这个注解
		//@Import三种类,一种是Import普通类,一种是Import ImportSelector,还有一种是Import ImportBeanDefinitionRegistrar
		//getImports(sourceClass)是获得import的内容,返回的是一个set
		processImports(configClass, sourceClass, getImports(sourceClass), 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的方法,可以看到获得了带有@Bean的方法后,不是马上转换成BeanDefinition,而是先用一个set接收
		// 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;
	}
  1. Внутренние классы обрабатываются рекурсивно и обычно не используются.
  2. Обработайте аннотацию @PropertySource, которая используется для загрузки файла свойств.
  3. Получите конкретное содержимое аннотации ComponentScan.Аннотация ComponentScan удаляет наиболее часто используемый basePackage, а также includeFilters, excludeFilters и т. д.
  4. Определите, был ли он помечен @ComponentScans или был вызван условием @Condition.Если условие выполнено, введите if и выполните следующие операции: 4.1 Выполните операцию сканирования и поместите отсканированные данные в набор Этот метод будет подробно объяснен позже. 4.2 Зациклить набор, чтобы определить, является ли он классом конфигурации, и если да, то рекурсивно вызвать метод анализа, поскольку сканируемый класс по-прежнему является классом конфигурации с аннотацией @ComponentScans или методом, отмеченным @Bean и т. д., поэтому это нужно сделать снова разбирается.
  5. Обрабатывая аннотацию @Import, @Import является очень важной аннотацией в Spring.Именно из-за своего существования Spring очень гибок.Будь то в Spring или сторонних технологиях, интегрированных с Spring, аннотация @Import широко используется , @Import имеет три случая: один — общий класс Import, один — Import ImportSelector, а другой — Import ImportBeanDefinitionRegistrar, getImports(sourceClass) — получить содержимое импорта и вернуть набор, этот метод будет объяснен в подробно позже .
  6. Обработка аннотаций @ImportResource.
  7. Для метода обработки @Bean видно, что после получения метода с @Bean он не конвертируется в BeanDefinition сразу, а сначала принимается с набором.

Давайте сначала посмотрим на метод в 4.1:

	public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
		//扫描器,还记不记在new AnnotationConfigApplicationContext的时候
		//会调用AnnotationConfigApplicationContext的构造方法
		//构造方法里面有一句 this.scanner = new ClassPathBeanDefinitionScanner(this);
		//当时说这个对象不重要,这里就是证明了。常规用法中,实际上执行扫描的只会是这里的scanner对象
		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);
		scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
				BeanUtils.instantiateClass(generatorClass));

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

		//addIncludeFilter addExcludeFilter,最终是往List<TypeFilter>里面填充数据
		//TypeFilter是一个函数式接口,函数式接口在java8的时候大放异彩,只定义了一个虚方法的接口被称为函数式接口
		//当调用scanner.addIncludeFilter  scanner.addExcludeFilter 仅仅把 定义的规则塞进去,并么有真正去执行匹配过程

		//处理includeFilters
		for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addIncludeFilter(typeFilter);
			}
		}

		//处理excludeFilters
		for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addExcludeFilter(typeFilter);
			}
		}

		boolean lazyInit = componentScan.getBoolean("lazyInit");
		if (lazyInit) {
			scanner.getBeanDefinitionDefaults().setLazyInit(true);
		}

		Set<String> basePackages = new LinkedHashSet<>();
		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);
		}
		// 从下面的代码可以看出ComponentScans指定扫描目标,除了最常用的basePackages,还有两种方式
		// 1.指定basePackageClasses,就是指定多个类,只要是与这几个类同级的,或者在这几个类下级的都可以被扫描到,这种方式其实是spring比较推荐的
		// 因为指定basePackages没有IDE的检查,容易出错,但是指定一个类,就有IDE的检查了,不容易出错,经常会用一个空的类来作为basePackageClasses
		// 2.直接不指定,默认会把与配置类同级,或者在配置类下级的作为扫描目标
		for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
			basePackages.add(ClassUtils.getPackageName(clazz));
		}
		if (basePackages.isEmpty()) {
			basePackages.add(ClassUtils.getPackageName(declaringClass));
		}

		//把规则填充到排除规则:List<TypeFilter>,这里就把 注册类自身当作排除规则,真正执行匹配的时候,会把自身给排除
		scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
			@Override
			protected boolean matchClassName(String className) {
				return declaringClass.equals(className);
			}
		});
		//basePackages是一个LinkedHashSet<String>,这里就是把basePackages转为字符串数组的形式
		return scanner.doScan(StringUtils.toStringArray(basePackages));
	}
  1. Определен сканер сканера. Помните ли вы, что при использовании нового AnnotationConfigApplicationContext будет вызываться конструктор AnnotationConfigApplicationContext. В конструкторе есть предложение. . При обычном использовании только объект сканера здесь будет фактически выполнять сканирование.
  2. Чтобы справиться с includeFilters, нужно добавить правила в сканер.
  3. Чтобы справиться с excludeFilters, нужно добавить правила в сканер.
  4. Проанализируйте basePackages, чтобы узнать, какие пакеты необходимо сканировать.
  5. Добавьте правило исключения по умолчанию: исключить себя.
  6. Выполните сканирование, подробное позже.

Здесь необходимо дополнительное пояснение.При добавлении правил просто поместите определенные правила в набор классов правил.Класс правил является функциональным интерфейсом.Интерфейс, который определяет только один виртуальный метод, называется функциональным интерфейсом.Стиль интерфейса ярко светит в java8 тут только правила вставлены, а правила сопоставления толком не реализованы.

Давайте посмотрим, как выполняется сканирование:

	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		//循环处理basePackages
		for (String basePackage : basePackages) {
			//根据包名找到符合条件的BeanDefinition集合
			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);
				//由findCandidateComponents内部可知,这里的candidate是ScannedGenericBeanDefinition
				//而ScannedGenericBeanDefinition是AbstractBeanDefinition和AnnotatedBeanDefinition的之类
				//所以下面的两个if都会进入
				if (candidate instanceof AbstractBeanDefinition) {
					//内部会设置默认值
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					//如果是AnnotatedBeanDefinition,还会再设置一次值
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

Поскольку базовых пакетов может быть несколько, их необходимо обрабатывать в цикле, и в конечном итоге компонент будет зарегистрирован. Давайте посмотрим на метод findCandidateComponents:

	public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		//spring支持component索引技术,需要引入一个组件,因为大部分情况不会引入这个组件
		//所以不会进入到这个if
		if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
			return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
		}
		else {
			return scanCandidateComponents(basePackage);
		}
	}

Spring поддерживает технологию индексации компонентов и нуждается в представлении компонента.Большинство проектов не вводят этот компонент, поэтому он войдет в метод scanCandidateComponents:

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			//把 传进来的类似 命名空间形式的字符串转换成类似类文件地址的形式,然后在前面加上classpath*:
			//即:com.xx=>classpath*:com/xx/**/*.class
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			//根据packageSearchPath,获得符合要求的文件
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			//循环资源
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}

				if (resource.isReadable()) {//判断资源是否可读,并且不是一个目录
					try {
						//metadataReader 元数据读取器,解析resource,也可以理解为描述资源的数据结构
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						//在isCandidateComponent方法内部会真正执行匹配规则
						//注册配置类自身会被排除,不会进入到这个if
						if (isCandidateComponent(metadataReader)) {
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setResource(resource);
							sbd.setSource(resource);
							if (isCandidateComponent(sbd)) {
								if (debugEnabled) {
									logger.debug("Identified candidate component class: " + resource);
								}
								candidates.add(sbd);
							}
							else {
								if (debugEnabled) {
									logger.debug("Ignored because not a concrete top-level class: " + resource);
								}
							}
						}
						else {
							if (traceEnabled) {
								logger.trace("Ignored because not matching any filter: " + resource);
							}
						}
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to read candidate component class: " + resource, ex);
					}
				}
				else {
					if (traceEnabled) {
						logger.trace("Ignored because not readable: " + resource);
					}
				}
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}
  1. Преобразуйте входящую строку, аналогичную форме пространства имен, в форму, аналогичную адресу файла класса, а затем добавьте путь к классу* впереди, а именно: com.xx=>путь к классу*:com/xx/**/*.class.
  2. В соответствии с packageSearchPath получите файлы, соответствующие требованиям.
  3. Документы, соответствующие требованиям, направляются для дальнейшего рассмотрения. Наконец, файлы, соответствующие требованиям, будут преобразованы в BeanDefinition и возвращены.

До сих пор метод, упомянутый в упомянутом выше 4.1, наконец, был проанализирован.Давайте посмотрим на метод обработки аннотации @Import на шаге 5, упомянутом выше:

	//这个方法内部相当相当复杂,importCandidates是Import的内容,调用这个方法的时候,已经说过可能有三种情况
	//这里再说下,1.Import普通类,2.Import ImportSelector,3.Import ImportBeanDefinitionRegistrar
	//循环importCandidates,判断属于哪种情况
	//如果是普通类,会进到else,调用processConfigurationClass方法
	//这个方法是不是很熟悉,没错,processImports这个方法就是在processConfigurationClass方法中被调用的
	//processImports又主动调用processConfigurationClass方法,是一个递归调用,因为Import的普通类,也有可能被加了Import注解,@ComponentScan注解 或者其他注解,所以普通类需要再次被解析
	//如果Import ImportSelector就跑到了第一个if中去,首先执行Aware接口方法,所以我们在实现ImportSelector的同时,还可以实现Aware接口
	//然后判断是不是DeferredImportSelector,DeferredImportSelector扩展了ImportSelector
	//如果不是的话,调用selectImports方法,获得全限定类名数组,在转换成类的数组,然后再调用processImports,又特么的是一个递归调用...
	//可能又有三种情况,一种情况是selectImports的类是一个普通类,第二种情况是selectImports的类是一个ImportBeanDefinitionRegistrar类,第三种情况是还是一个ImportSelector类...
	//所以又需要递归调用
	//如果Import ImportBeanDefinitionRegistrar就跑到了第二个if,还是会执行Aware接口方法,这里终于没有递归了,会把数据放到ConfigurationClass中的Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars中去
	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 (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
							this.deferredImportSelectors.add(
									new DeferredImportSelectorHolder(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();
			}
		}
	}

Примерная функция этого метода написана в комментариях, поэтому повторяться не буду.

До сих пор метод processConfigBeanDefinitions в ConfigurationClassPostProcessor был кратко передан.

Но это еще не конец, processConfigBeanDefinitions — это метод в интерфейсе BeanDefinitionRegistryPostProcessor, BeanDefinitionRegistryPostProcessor расширяет BeanFactoryPostProcessor, а метод postProcessBeanFactory еще не проанализирован, что делает этот метод, проще говоря — судить, является ли класс конфигурации Lite конфигурацией. класс или полная конфигурация.Класс, если это класс конфигурации, будет проксироваться Cglib, цель состоит в том, чтобы обеспечить область действия bean-компонента. Этот метод действительно сложен.Ввиду ограниченности места я не буду здесь продолжать.Заинтересованные друзья могут зайти на мой GitHub посмотреть,там простой анализ(конечно,есть еще много вещей,которые нельзя отразить в блоге,если Выкладывать все это было бы слишком долго, но на GitHub есть комментарии).

Подведем итоги.Метод processConfigBeanDefinitions в ConfigurationClassPostProcessor очень важен, в основном для завершения сканирования и, наконец, регистрации определяемых нами bean-компонентов.