Springboot自动装配原理-详细版本

Springboot自动装配原理-详细版本

一、认识下@SpringBootApplication注解

1、展开@SpringBootApplication

//标记使用位置 元注解
@Target(ElementType.TYPE)
//标记注解使用的阶段 元注解
@Retention(RetentionPolicy.RUNTIME)
//标记形成javadoc文档时注解显示 元注解
@Documented
//标记其子类能继承这个注解 修饰注解
@Inherited
//集成注解SpringBootConfiguration  核心
@SpringBootConfiguration
//集成注解EnableAutoConfiguration  核心
@EnableAutoConfiguration
//扫描包下bean,不配置包名,默认扫描包或者子包下面的bean @Filter过滤
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}

2、展开@SpringBootConfiguration

//上面三个不重复说明
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//标记为配置类
@Configuration
public @interface SpringBootConfiguration {
}

3、展开@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//组合注解 
@AutoConfigurationPackage
//引入bean注入
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}

关于@Import注解的介绍,查看下面链接
@Import介绍链接地址
4、展开@AutoConfigurationPackage注解

//上面三个之前已说明
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//标记子类能继承
@Inherited
//引入bean注入
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}

从以上层层展开可以看出其@SpringBootApplication注解核心就是@Import导入bean和@ComponentScan扫描,其中@ComponentScan扫描就不用多说了,再看下@Import,主要的两个类AutoConfigurationPackages.RegistrarAutoConfigurationImportSelector

二、AutoConfigurationPackages.Registrar类registerBeanDefinitions方法

为什么要直接提registerBeanDefinitions方法?
因为@Import使用的方法,大家还是先看下@Import的基础使用

	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImport(metadata).getPackageName());
		}
}

可以看出获取到了启动类下的包名路径,根据@import的用法,
registerBeanDefinitions这里注册的bean就会被实例化出来
在这里插入图片描述
接下来,进入register方法

	public static void register(BeanDefinitionRegistry registry, String... packageNames) {
	    //是否包含BEAN,这里不包含,BEAN就是AutoConfigurationPackages类名
		if (registry.containsBeanDefinition(BEAN)) {
			BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
			ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
			constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));
		}
		else {
	        //创建GenericBeanDefinition对象
			GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
			//设置bean的类class
			beanDefinition.setBeanClass(BasePackages.class);
			//设置bean其他的信息
			beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
			//设置bean角色的信息beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			//把BasePackages注册至注册器
			registry.registerBeanDefinition(BEAN, beanDefinition);
		}
	}

可以在bean工厂中看出,注册进去的是名字为
org.springframework.boot.autoconfigure.AutoConfigurationPackages,beanclass确实其内部内BasePackages
在这里插入图片描述
所以综上所述,就是注册了AutoConfigurationPackages$BasePackages类

三、 AutoConfigurationImportSelector类selectImports方法

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

	private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry();

	private static final String[] NO_IMPORTS = {};

	private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);

	private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";

	private ConfigurableListableBeanFactory beanFactory;

	private Environment environment;

	private ClassLoader beanClassLoader;

	private ResourceLoader resourceLoader;

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

这里就非常奇怪了,按照@Import的使用,肯定会执行selectImports方法,现在没有执行,原因究竟是什么呢?
在这里插入图片描述
接下来观察,这里实现的是DeferredImportSelector接口
在这里插入图片描述
在这里插入图片描述
对DeferredImportSelector的详细解释
然后执行了这个方法
在这里插入图片描述
然后执行了AutoConfigurationGroup类的process方法在这里插入图片描述
接下来进入这个方法
在这里插入图片描述
这个地方可以看见把配置的文件的全限定类名给加载出来了
在这里插入图片描述
这个方法就很厉害了
**loadFactoryNames()**获取类名
在这里插入图片描述
这就是根据
org.springframework.boot.autoconfigure.EnableAutoConfiguration获取配置的类名在这里插入图片描述
可以看出这里已经缓存起来了
在这里插入图片描述
这里可以看出来,缓存里面就有org.springframework.boot.autoconfigure.EnableAutoConfiguration
在这里插入图片描述
然后根据EnableAutoConfiguration获取配置的124个权限定类名
在这里插入图片描述
那么接下来我们就来找寻下这个缓存到底哪里来的?

重新打断点,然后这个loadSpringFactories()再来一次

在这里插入图片描述
可以看出init初始化的时候,在创建SpringApplication对象的时候就调用了loadFactoryNames()
在这里插入图片描述
初次加载存入缓存之中时,
META-INF/spring.factories这个文件加载到缓存之中。。在这里插入图片描述
这里就是加载文件的位置,然后所有META-INF/spring.factories文件都会被加载进来,然后初始化时缓存起来,后续用到的时候就通过前面指定的全限定类取出。。。。
在这里插入图片描述
这个地方搞清楚了,然后回到这里,拿到了124个类名,从之前缓存中获取出来的。
在这里插入图片描述

在这里插入图片描述
看看spring去除重复~
在这里插入图片描述
接下来排除不需要用到的,不要浪费空间
在这里插入图片描述
过滤不需要加载的类
在这里插入图片描述
点击进入,这个方法很明显拿到了三个过滤器,并且是生成好的对象。
在这里插入图片描述
这个是在配置文件中配好的几个过滤器
在这里插入图片描述
接下来进行过滤
在这里插入图片描述
这个地方就可以看过滤使用的就是OnClassCondition类,这里就是需要了解@ConditionalOnClass和@ConditionalOnMissingClass的常用法~
了解链接地址

在这里插入图片描述
有些类就被过滤掉,数组位置用null替换掉了
在这里插入图片描述
可以断点进入这个过滤的方法。。这里就是整个把需要过滤的全限定类去重,对比的过程
在这里插入图片描述
这个地方我们看下这里486个排除的类名哪里来的,往前翻下代码,重新debug

在这里插入图片描述

在这里插入图片描述
然后进入这个方法
在这里插入图片描述
再次进入,发现这个地方加载的是META-INF/spring-autoconfigure-metadata.properties配置文件
在这里插入图片描述
进入发现了不一样的风景,看到罗列的一些键值对,很熟悉的感觉,尤其是ConditionOnClass
在这里插入图片描述
最后获得出需要加载的类

四、自动装配源码

其实可以看出,什么时候执行的自动装配,就必须知道@Import方法什么时候被解析处理的,上面的仅仅只是看出了加载到配置文件的类名。同时留下一个问题。
1、@Import什么时候触发的解析呢?
先写一个案例,然后一步一步的深入去看

package smoketest.freemarker;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class SampleWebFreeMarkerApplication {

	public static void main(String[] args) {
		SpringApplication.run(SampleWebFreeMarkerApplication.class, args);
	}

}

这里采用springboot源码下载后freemark测试方法来看的

进入run方法

	/**
	 * Static helper that can be used to run a {@link SpringApplication} from the
	 * specified sources using default settings and user supplied arguments.
	 * @param primarySources the primary sources to load
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return the running {@link ApplicationContext}
	 */
	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		//创建SpringApplication对象,然后传入的启动类class和参数
		return new SpringApplication(primarySources).run(args);
	}

先是new出SpringApplication类。再调用run方法,new的时候进行了一下初始化,spring的常规骚操作

	/**
	 * Create a new {@link SpringApplication} instance. The application context will load
	 * beans from the specified primary sources (see {@link SpringApplication class-level}
	 * documentation for details. The instance can be customized before calling
	 * {@link #run(String...)}.
	 * @param resourceLoader the resource loader to use
	 * @param primarySources the primary bean sources
	 * @see #run(Class, String[])
	 * @see #setSources(Set)
	 *
	 * 创建一个新的 {@link SpringApplication} 实例。
	 * 应用程序上下文将从指定的主要来源加载 bean(有关详细信息,请参阅 {@link SpringApplication class-level} 文档。
	 * 可以在调用 {@link run(String...)} 之前自定义实例。
	 * @param resourceLoader 资源加载器使用
	 * @param primarySources 主要 bean 源 @see run(Class, String[]) @see setSources(Set)
	 *
	 *   @SuppressWarnings   作用:告诉编译器忽略指定的警告,不用在编译完成后出现警告信息。
	 *   告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
	 *
	 * 初始化SpringApplication对象 并且加载了监听器类和初始化上下文类集合
	 *
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		//初始化资源加载器 这里传输的值为null
		this.resourceLoader = resourceLoader;
		//判断primarySources 传输的启动类为空就会报这个错误
		Assert.notNull(primarySources, "PrimarySources must not be null");
		//这里会new一个LinkedHashSet存储传入进来的值 primarySources先转化为list 在转化为LinkedHashSet ,也有去重复的参数,然后按照输入顺序排序
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		//这里是指定web的选用类型 WebApplicationType是个枚举 一般情况就是servlet
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		//设置参数 设置上下文初始化集合,通过getSpringFactoriesInstances方法获取 ApplicationContextInitializer类型的 (自动装配上下文初始化器)
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//设置参数 设置监听器集合实例化,通过getSpringFactoriesInstances方法获取 ApplicationListener类型的  配置的监听器类加载 (自动装配监听器初始化器)
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		//启动类的实例化创建
		this.mainApplicationClass = deduceMainApplicationClass();
	}

再回到run方法调用,进入SpringApplication核心方法

/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 *
	 * 运行 Spring 应用程序,创建并刷新一个新的
	 * {@link ApplicationContext}。
	 * @param args 应用程序参数(通常从 Java 主方法传递)
	 * @return 正在运行的 {@link ApplicationContext}
	 *
	 * springboot的主要运行地方
	 */
	public ConfigurableApplicationContext run(String... args) {
		//创建计时器 为了后面输出日志用的
		StopWatch stopWatch = new StopWatch();
		//计时器开始
		stopWatch.start();
		//初始定义ConfigurableApplicationContext  配置上下文应用类
		ConfigurableApplicationContext context = null;
		//创建springboot异常记录或者报告集合
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//设置java.awt.headless 为key的系统参数 ,没有就默认为true的字符串
		configureHeadlessProperty();
		//获取从spring.factories文件中加载的SpringApplicationRunListener 类型的监听器集合(也是自动装配监听器)
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//开始监听
		listeners.starting();
		try {
			//创建ApplicationArguments参数应用对象
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			//准备环境,传入之前实例化的监听器和参数应用对象
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			//environment配置忽略 Bean 信息
			configureIgnoreBeanInfo(environment);
			//这里就是springboot的banner打印处理,玩banner骚操作就可以在这里去改吧改吧
			Banner printedBanner = printBanner(environment);
			//创建上下文对象,根据web的类型创建不同上下文对象,我们这里是servlet 所以创建AnnotationConfigServletWebServerApplicationContext
			//org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext 创建
			context = createApplicationContext();
			//从spring.factories文件中获取SpringBootExceptionReporter类型的并且实例化,getSpringFactoriesInstances()方法很多地方用,自动装配配置文件加载并实例
			//然后添加至exceptionReporters集合
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//准备context类,其实就是添加属性,比如context、environment环境对象、listeners监听器呀等等
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			//这里就是调用原来spring的入口了,refresh刷新context,看过spring源码就必须对这个方法非常熟悉
			refreshContext(context);
			//上下文处理完成后续内容
			afterRefresh(context, applicationArguments);
			//计时器结束
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			//发布ApplicationStartedEvent事件,发出结束执行的事件
			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;
	}

因为我们这里主要研究是自动装配,其他点先不看,这里可以看出,只有5个默认处理器注册到bean工厂和启动类注册,其他自动装配的类还没有注册进入,那我们就先需要找到入口
在这里插入图片描述进入refreshContext方法
在这里插入图片描述
再去进入refresh(0方法,这里就进入spring最核心的代码了,AbstractApplicationContext类中,刚才根据web类型创建的上下文对象就是AbstractApplicationContext子类,通过子类调用refresh,就进入AbstractApplicationContext中,父类继承下去的方法,这里采用的模板设计模式。

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

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

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

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

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

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

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

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

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

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

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

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

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

然后进入看到invokeBeanFactoryPostProcessors这个方法,前几个步就是bean工厂DefaultListableBeanFactory初始化一些属性,这里发现bean工厂中还是只有6个注册,所以这里还是没有加载到,前几个都是spring的源码,这里不细讲,然后进入这个方法处理
在这里插入图片描述

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		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()));
		}
	}

然后进入invokeBeanFactoryPostProcessors调用BeanFactory后置处理器。下面这段代码非常长,也是spring中非常核心的一部分代码,各种BeanFactory后置处理器的调用

这里提前看下DefaultListableBeanFactory的UML图
在这里插入图片描述
在这里插入图片描述
后置处理器也有三个,源码默认产生的
这里的Bean工厂就是DefaultListableBeanFactory

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

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		//如果有的话,首先调用 BeanDefinitionRegistryPostProcessors。
		//创建一个processedBeans空集合
		Set<String> processedBeans = new HashSet<>();
		//如果beanFactory属于BeanDefinitionRegistry类型
		if (beanFactory instanceof BeanDefinitionRegistry) {
	        //然后强制转化
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			//创建一个空的list 存放BeanFactoryPostProcessor
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			//又创建一个空的list 存放BeanDefinitionRegistryPostProcessor
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
			//循环遍历传入进来的后置处理器
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			    //如果属于BeanDefinitionRegistryPostProcessor类型的
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				//强制转化
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
				  //执行postProcessBeanDefinitionRegistry方法,其实就是注册后置处理器,添加到registry中,
				  //也就是       DefaultListableBeanFactory中,所以beanmap的注册数中多了后置处理器的map值
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					//添加至之前创建的集合
					registryProcessors.add(registryProcessor);
				}
				else {
				   //否则直接添加regularPostProcessors集合中
					regularPostProcessors.add(postProcessor);
				}
			}
			//前面的过程大概执行了,区分出BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor分别放入两个集合,属于BeanDefinitionRegistryPostProcessor会调用postProcessBeanDefinitionRegistry,注册后置处理器。

			// 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.
			//不要在此处初始化 FactoryBeans:我们需要让所有常规 bean 保持未初始化状态,以便 bean 工厂后处理器应用到它们!           将实现 PriorityOrdered、Ordered 和其余部分的 BeanDefinitionRegistryPostProcessor 分开。
			//创建BeanDefinitionRegistryPostProcessor类型的集合
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			//首先,调用实现 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor。
			//获取BeanDefinitionRegistryPostProcessor类型下的后置处理器名字,就是刚加进去的那个名
			//org.springframework.context.annotation.internalConfigurationAnnotationProcessor
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			//遍历postProcessorNames 
			for (String ppName : postProcessorNames) {
			    //类型匹配PriorityOrdered类型
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//如果属于,获取改类名的实例bean加入到currentRegistryProcessors集合中
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					//过程beans集合添加ppName值
					processedBeans.add(ppName);
				}
			}
			//排序后置处理器
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//全部currentRegistryProcessors添加至registryProcessors集合中
			registryProcessors.addAll(currentRegistryProcessors);
			//调用调用BeanDefinitionRegistry后处理器
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
	        //清空currentRegistryProcessors
			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);
			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);
				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();
	}

在执行95行代码的时候,执行BeanDefinitionRegistry后置处理器的时候成功的载入了bean信息到bean工厂,注册上去了,
在这里插入图片描述
进入95行代码仔细研究~~
postProcessors只有一个,前面从工厂中获取出来的ConfigurationClassPostProcessor后置处理器

	/**
	 * Invoke the given BeanDefinitionRegistryPostProcessor beans.
	 * 调用给定的 BeanDefinitionRegistryPostProcessor bean。
	 */
	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}

执行BeanDefinitionRegistryPostProcessor后置处理器实例ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry方法


	/**
	 * Derive further bean definitions from the configuration classes in the registry.
	 */
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	    //Object的hashCode方法是根据对象内存地址返回一个hash值,但是很多类都会重写hashCode方法。
//JDK在System类中提供一个方法public static native int identityhashCode(Object x)
//不管给的参数对象的类是否重载了hashCode()方法,identityHashCode方法都会返回Object类默认hashCode()方法会返回的值
	    //获取hash值
		int registryId = System.identityHashCode(registry);
		//registriesPostProcessed集合保包含registryId就报错 postProcess BeanDefinitionRegistry 已经在这个后处理器上调用过
		if (this.registriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
		}
		//factoriesPostProcessed集合保包含registryId就报错 postProcessBeanFactory 已经再次调用了这个后处理器
		if (this.factoriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + registry);
		}
		//调用后添加hash值
		this.registriesPostProcessed.add(registryId);
		//上面意思就是只允许调用postProcessBeanDefinitionRegistry和postProcessBeanFactory调用一次,再调用就报错
		//核心的调用还是processConfigBeanDefinitions方法,过程配置bean的定义
		processConfigBeanDefinitions(registry);
	}

进入processConfigBeanDefinitions方法
这个地方需要了解下beanDef.getAttribute()判断的什么
了解地址

	/**
	 * Build and validate a configuration model based on the registry of
	 * {@link Configuration} classes.
	 */
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	    //创建一个空的BeanDefinitionHolder集合 BeanDefinition持有者
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		//获取已经注册在工厂的beanName数组
		String[] candidateNames = registry.getBeanDefinitionNames();
		//循环遍历
		for (String beanName : candidateNames) {
		    //根据名字获取BeanDefinition,bean的定义信息都在里面
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			//ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE值为org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass,这里beanDef.getAttribute获取出来configurationClass值不为null,说明以及被解析过的
			//这里就是判断是不是configurationClass配置类,有没有被解析过
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
			//如果不为null,打印日志 Bean 定义已经作为配置类处理
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			//检查是不是配置类
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
			   //如果是配置类添加configCandidates,包装在BeanDefinitionHolder中
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

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

		// Sort by previously determined @Order value, if applicable
		//按先前确定的@Order值排序
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// Detect any custom bean name generation strategy supplied through the enclosing application context
		//检测通过封闭应用程序上下文提供的任何自定义bean名称生成策略
		SingletonBeanRegistry sbr = null;
		//判断属于SingletonBeanRegistry
		if (registry instanceof SingletonBeanRegistry) {
	       //强制转化
			sbr = (SingletonBeanRegistry) registry;
			//localBeanNameGeneratorSet默认值为false,本地bean名字生成器集
			if (!this.localBeanNameGeneratorSet) {
			  //获取单例
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				//如果存在
				if (generator != null) {
				    //赋值componentScanBeanNameGenerator
					this.componentScanBeanNameGenerator = generator;
					//赋值importBeanNameGenerator
					this.importBeanNameGenerator = generator;
				}
			}
		}
		//判断是否有环境对象
		if (this.environment == null) {
		     //如果不存在就创建一个StandardEnvironment标准环境对象
			this.environment = new StandardEnvironment();
		}

		// Parse each @Configuration class
		//解析每个 @Configuration 类 ,解析配置类,创建ConfigurationClassParser解析器
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
		//过滤配置类,防止重复
		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		//创建个alreadyParsed集合,存放已经解析了的配置类
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		//循环解析
		do {
		    //解析配置类,重要的地方 @Import解析就会在这里入口的
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
		while (!candidates.isEmpty());

		// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
		if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
			// Clear cache in externally provided MetadataReaderFactory; this is a no-op
			// for a shared cache since it'll be cleared by the ApplicationContext.
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

后面parse解析

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			try {
				if (bd instanceof AnnotatedBeanDefinition) {
				   //如果是注解类就执行这个parse解析
					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);
			}
		}
        //这里就是DeferredImportSelectorl处理器处理
		this.deferredImportSelectorHandler.process();
	}

这里处理所有配置类

    //处理所有配置类
	protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
	}

进入processConfigurationClass方法

	protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) 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, filter);
		do {
		     //循环一个一个配置类的解析
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}
		while (sourceClass != null);

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

这里就是解析配置类上的每个注解~@Component、@Import等等

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

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

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

		// Process any @ComponentScan annotations
		处理@ComponentScan 注解
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// Process any @Import annotations
		//处理@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);
			}
		}

		// Process individual @Bean methods
		//处理@Import注解 
		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
		// 如果没有父类需要处理就返回null,表示循环结束
		return null;
	}

然后进入process()解析

		public void process() {
		    //
			List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
			this.deferredImportSelectors = null;
			try {
				if (deferredImports != null) {
					DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
					deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
					deferredImports.forEach(handler::register);
					handler.processGroupImports();
				}
			}
			finally {
				this.deferredImportSelectors = new ArrayList<>();
			}
		}

然后去看解析@Import的地方,processImports方法进入,这里很重要的点,下面解析,循环处理就是按照几种实现方式不同,就不同的 处理。。
下面循环中判断了如果实现了DeferredImportSelector交给deferredImportSelectorHandler,然后后续处理,如果实现的普通ImportSelector,才会调用selectImports()方法,代码中也有注释,可以很清晰的看到这点逻辑
在这里插入图片描述

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

		if (importCandidates.isEmpty()) {
			return;
		}

		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			this.importStack.push(configClass);
			try {
				for (SourceClass candidate : importCandidates) {
				 //实现ImportSelector接口的这里处理
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						Class<?> candidateClass = candidate.loadClass();
						//创建ImportSelector实例对象
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						//获取过滤
						Predicate<String> selectorFilter = selector.getExclusionFilter();
						if (selectorFilter != null) {
							exclusionFilter = exclusionFilter.or(selectorFilter);
						}
						//如果属于DeferredImportSelector类型 非常重点
						if (selector instanceof DeferredImportSelector) {
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
						//如果没有实现就执行selectImports()方法
							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)) {
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						Class<?> candidateClass = candidate.loadClass();
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					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), exclusionFilter);
					}
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to process import candidates for configuration class [" +
						configClass.getMetadata().getClassName() + "]", ex);
			}
			finally {
				this.importStack.pop();
			}
		}
	}

借用网上大佬的一幅很形象的流程图描述这个过程!
在这里插入图片描述
这里的handle方法主要就是一个添加实现DeferredImportSelector的收集到集合中

		public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
			DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
			if (this.deferredImportSelectors == null) {
				DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
				handler.register(holder);
				handler.processGroupImports();
			}
			else {
				this.deferredImportSelectors.add(holder);
			}
		}

然后回到
在这里插入图片描述
这里就是DeferredImportSelector处理器进行处理

		public void process() {
		//获取之前DeferredImportSelectorHolder收集器
			List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
			this.deferredImportSelectors = null;
			try {
				if (deferredImports != null) {
			       //获取处理器
					DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
					//多个排序
					deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
					//注册需要处理的import
					deferredImports.forEach(handler::register);
					handler.processGroupImports();
				}
			}
			finally {
				this.deferredImportSelectors = new ArrayList<>();
			}
		}
	}

进入处理register方法,这里很清晰的看见
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup()
调用了getImportGroup(),回到了最初AutoConfigurationImportSelector
在这里插入图片描述

		public void register(DeferredImportSelectorHolder deferredImport) {
		    //获取group对象,就是AutoConfigurationImportSelector实现的返回AutoConfigurationGroup
			Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
			//这行代码就是,如果group为null说明没有重新getImportGroup()方法,否则就使用原来的importSelector方法
			DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
					(group != null ? group : deferredImport),
					key -> new DeferredImportSelectorGrouping(createGroup(group)));
			grouping.add(deferredImport);
			this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
					deferredImport.getConfigurationClass());
		}

然后就是执行processGroupImports()方法

然后这里面grouping.getImports()方法执行process方法

		public void processGroupImports() {
			for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
				Predicate<String> exclusionFilter = grouping.getCandidateFilter();
				grouping.getImports().forEach(entry -> {
					ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
					try {
						processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
								Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
								exclusionFilter, false);
					}
					catch (BeanDefinitionStoreException ex) {
						throw ex;
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to process import candidates for configuration class [" +
										configurationClass.getMetadata().getClassName() + "]", ex);
					}
				});
			}
		}

这里先执行process方法,回到最开始看到的

		public Iterable<Group.Entry> getImports() {
			for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
				this.group.process(deferredImport.getConfigurationClass().getMetadata(),
						deferredImport.getImportSelector());
			}
			return this.group.selectImports();
		}

这里就是最开始解析spring.factories配置文件中EnableAutoConfiguration的类,所以就是自动装配的原理点,然后加载到spring的bean工厂中

		@Override
		public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
			Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
					() -> String.format("Only %s implementations are supported, got %s",
							AutoConfigurationImportSelector.class.getSimpleName(),
							deferredImportSelector.getClass().getName()));
			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
					.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
			this.autoConfigurationEntries.add(autoConfigurationEntry);
			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
		}

五、看懂了源码有什么用?

好处:
1、知道底层原理,遇到相关问题也能自己处理;
2、需要扩展spring的时候也可以改造;
3、增加了自己的技术水平,同时面试也牛批些

六、自动装配运用——手写个starter

1、首先建立个maven工程
2、不引入其他依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.loyu</groupId>
    <artifactId>spring-starter-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>

3、创建一个Computer 类

package com.loyu.pojo;

/**
 * @Author : yulongjun
 * @Date : 01/04/2022
 * @Description deloitte develop
 */
public class Computer {


    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

4、创建META-INF文件夹下spring.factories文件,配置key为EnableAutoConfiguration,value为Computer 全限定里面
在这里插入图片描述
5、然后maven clean install后
6、引入到另外一个项目中
在这里插入图片描述
然后获取bean信息

@SpringBootApplication
public class TestApplication {


    /**
     * 启动类
     * @param args
     */
    public static void main (String[] args){

        ApplicationContext context =SpringApplication.run(TestApplication.class, args);
//        Object bean = context.getBean("xxxx");
//        Object bean1 = context.getBean("org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration");
//        System.out.println(bean);
//        System.out.println(bean1);
//        System.out.println("启动完成~");
//        AnnotatedBeanDefinition application = (AnnotatedBeanDefinition) context.getBeanDefinition("TestApplication");
//        AnnotationMetadata metadata = application.getMetadata();
//        Map<String, Object> attributes = metadata.getAnnotationAttributes(SpringBootApplication.class.getName());
//        System.out.println(attributes);


        Computer bean = (Computer) context.getBean("com.loyu.pojo.Computer");
        System.out.println(bean);

    }
    }

结果打印出来了Computer实例化出来的对象
在这里插入图片描述
@Conditional(TestCondition.class)

这句代码可以标注在类上面,表示该类下面的所有@Bean都会启用配置,也可以标注在方法上面,只是对该方法启用配置。

@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)

另外介绍几个条件注解,其实都是@Conditional基础上实现的,这里过滤按条件加载
其他大佬介绍这几个注解

其他就讲到这里了,上面讲述了springboot自动装配的整体结构,最终解析spring.factories配置通过import注册到到bean工厂中,后续经过bean的装配到spring单例池中。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值