springBoot自动装配


在这里插入图片描述
spring对象生命周期提供的扩展点:

1、BeanFactoryPostProcessor:实例化对象之前
2、BeanNameAware:设置容器中bean的名称
3、BeanFactoryAware:返回对象实例的beanFactory
4、BeanPostProcessor
5、InitializingBean
6、ApplicationContextAware
......

factoryBean 和 beanFactory

相同点:都是用来创建对象的
不同:
	factoryBean 更像是一种标准的生产线,需要经过完整的步骤和过程才能生成具体的对象
	beanFactory:更像是用户自定义,根据用户需求创建出具体对象

对象注入容器@Import:

	可以导入添加了@Configuration的类
	也可以直接导入类
	导入实现了importSelector接口的类
	导入实现ImportBeanDefinitionRegistrar接口

有条件的注入:Conditional注解

@ConditionalOnBean、@ConditionalOnClass、@ConditionalOnMissingBean......

提高对象注入效率:@indxed

编译时将所有需要注入的对象写道一个文件中,在注入时就不需要做包的扫描,直接读取这个文件就行了

springboot自动装配

@SpringBootApplication注解

其实是一个复合注解
在这里插入图片描述

run方法和SpringBootApplication注解怎么联系起来的

包含confuguration注解,主类本身会作为配置类扫描到创建对象放入容器中,在spring对象的生命周期中有configuration注解
对应的beanFactoryPostProceessor扩展类:configurationClassPostProcessor
在创建beanDefinition后会执行postProcessBeanFactory()会处理类上的其他注解,进而会处理到import注解

在这里插入图片描述

这里又会调用自身的processConfigurationBeanDefinition(),这个方法中会使用ConfigurationClassParser来解析配置类
(因为加了configuration注解)

在这里插入图片描述

parse方法解析配置类

在这里插入图片描述

调用重载的parse方法

在这里插入图片描述

都会调用自身的processConfigurationClass方法

在这里插入图片描述

真正的业务方法:doProcessConfigurationClass()

在这里插入图片描述

真正解析import注解

在这里插入图片描述

AutoConfigurationImportSelector就实现了DeferredImportSelector接口

在这里插入图片描述
在这里插入图片描述

所以在解析import注解时发现导入的类实现了DeferredImportSelector,不会去掉selectImports()方法,而是调用handle

在这里插入图片描述

最终会调用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里就会调用DeferredImportSelector接口的类部类group的process()方法

在这里插入图片描述

AutoConfigurationImportSelector实现的process方法,从spring.factory文件读取自动装配类

在这里插入图片描述

这样就和AutoConfigurationImportSelector联系起来了,自动装配的流程就更完善了

SpringBootConfiguration

就是一个configuration注解
在这里插入图片描述

ComponentScan

扫描要把对象注入容器的包(类上有@configuration、@component、@service…就会被放入ioc容器中管理)

EnableAutoConfiguration

又是一个复合注解
在这里插入图片描述
重点看这个:@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector的作用:

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		//获取资源文件下:MEAT-INF下的spring.factory文件中的全路径类名
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		//去重
		configurations = removeDuplicates(configurations);
		//去掉排除在外的(@SpringBootApplication中的exclude
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		//去掉排除在外的(@SpringBootApplication中的exclude
		configurations.removeAll(exclusions);
		//根据过滤器过滤掉部分
		configurations = getConfigurationClassFilter().filter(configurations);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

getCandidateConfigurations(annotationMetadata, attributes);从spring.factory文件中获取key为EnableAutoConfiguration的所有类
在这里插入图片描述

getSpringFactoriesLoaderFactoryClass()就是EnableAutoConfiguration的全路径类名
在这里插入图片描述
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader())
在这里插入图片描述

loadSpringFactories
在这里插入图片描述
FACTORIES_RESOURCE_LOCATION就是META-INF/spring.factories
在这里插入图片描述
这样就把所有srping.factory文件中以org.springframework.boot.autoconfigure.EnableAutoConfiguration为key的所有值全部拿到
在这里插入图片描述
过滤部分自动装配类:这是除了使用OnConditional注解的另一中有条件的注入,根据META-INF/spring-autoconfigure-metadata.properties文件中的配置过滤
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

至此已经了解到SpringBootConfiguration注解的作用,那么注解是在什么时候起作用的?

SpringApplication.run方法

点进去可以发现分为两部分:1、创建SpringApplication类,2、然后调用其run方法
在这里插入图片描述

创建SpringApplication类

调用构造方法创建SpringApplication类

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		//推断程序是否是web应用(如果是:是servlet还是reactive类型)
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		//从系统资源文件spring.factory下找到以BootstrapRegistryInitializer为Key的所有类,添加进集合
		this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
		//从系统资源文件spring.factory下找到以ApplicationContextInitializer为Key的所有类,添加进集合
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//从系统资源文件spring.factory下找到以ApplicationListener为Key的所有类,添加进集合
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		//找到main方法所在类
		this.mainApplicationClass = deduceMainApplicationClass();
	}

run方法

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		//计时开始
		stopWatch.start();
		//根据创建SpringApplication类时添加的bootstrapRegistryInitializers集合创建bootstrapContext
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();
		//找到系统资源文件下spring.factory中以SpringApplicationRunListener为key的所有类
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			//重点,刷新容器
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}

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

refreshContext(context):最终会调用AbstractApplicationContext下的refresh方法

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
			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 {
				postProcessBeanFactory(beanFactory);
				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");	
				//实例化对象并调用BeanFactoryPostProcessors后置增强器
				//从spring.facotry文件中读取的以EnableAutoConfiguration为Key的所有自动装配类在这里面完成对象实例化
				invokeBeanFactoryPostProcessors(beanFactory);
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();
				// Initialize message source for this context.
				initMessageSource();
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();
				// Initialize other special beans in specific context subclasses.
				onRefresh();
				// Check for listener beans and register them.
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);
				// Last step: publish corresponding event.
				finishRefresh();
			}
			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				destroyBeans();
				cancelRefresh(ex);
				throw ex;
			}
			finally {
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

总结自动装配原理:

0、包含confuguration注解,主类本身也会被扫描创建对象放入容器中,
在spring对象的生命周期中有configuration注解对应的beanFactoryPostProceessor(configurationClassPostProcessor)包含confuguration注解,
主类本身也会被扫描创建对象放入容器中,在spring对象的生命周期中有configuration注解对应的
beanFactoryPostProceessor,在创建beanDefinitionhou会处理类上的其他注解,
进而会处理到import注解,在创建beanDefinitionhou会处理类上的其他注解,进而会处理到import注解
1、SpringBootApplication注解中的EnableAutoConfiguration注解导入了AutoConfigurationImportSelector类,这个类的作用
就是把spring.factory文件中以EnableAutoCinfiguration为key的所有自动装配类名:getAutoConfigurationEntry方法,通过
conditional注解和META-INF/spring-autoconfigure-metadata.properties中的配置进行过滤得到最终要加载进内存
2、springApplication的run方法最终会通过refreshContext()->refresh()->invokeBeanFactoryPostProcessors(beanFactory)->.....
最终调用到AutoConfigurationImportSelector中的getAutoConfigurationEntry(),拿到所有自动装配的类名后,通过反射创建对
象(@configuration、@bean、@component等注解)

自定义starter

明白了springboot自动装配原理,那么自定义starter就很简单

1、创建一个starter项目,定义一个自动装配类使用@configuration和@bean或者是@componentScan搭配使用,使用
	conditional注解或者在资源文件下创建META-INF/spring-autoconfigure-metadata.properties设置自动装配的条件
2、在资源文件下创建META-INF/spring.factory文件:内容为k=v形式,key就是org.springframework.boot.autoconfigure,
	value是自定义的自动装配类群全路径类名
	如果想要实现别的项目引入starter之后编写application配置文件有自动提示的效果:在MEAT-INF下创建additional-spring-configuration-metadata.json文件
	,并填写响应的文件

在这里插入图片描述

3、打包项目,在其他springboot项目中引入即可
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值