SpringBoot自动装配原理

spring mvc的自动配置

  • 自动配置ViewResolver(视图解析器:根据方法的返回值得到视图对象(view),视图对象决定如何渲染(转发/重定向))。
  • ViewResolver组合所有的视图解析器。
  • 可以自己定制一个视图解析器。
  • 静态资源文件夹webjars、静态首页访问(index.html)、favicon.ico
  • 自动注册Converter转换器、Formatter格式化器
  • 自己给容器中添加HttpMessageConverter,只需要将自己的组件注册的容器中。
  • 配置一个ConfigurableWebBindingInitializer替换默认

源码细节

@SpringBootApplication
	SpringApplication.run(xxxxxxApplication.class, args);
	@SpringBootConfiguration
		@Configuration
			@Component
	@EnableAutoConfiguration
		@AutoConfigurationPackage
			@Import(AutoConfigurationPackages.Registrar.class)   [重点] 设置当前配置所在的包作为扫描包,后续针对当前包进行扫描
		@Import(AutoConfigurationImportSelector.class)  [重点] 设置自动装配的选择器
	@ComponentScan(excludeFilters = { 
			@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
			@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

分析自动装配原理

在META-INF/spring.factories中自定义配置类

SpringBoot启动流程

核心思想:

1、初始化各种属性,加载成对象

  • 读取环境属性(Environment)
  • 系统配置(spring.factory)
  • 参数(Arguments、application.yaml)

2、创建spring容器对象ApplicationContext,加载各种配置。

3、创建容器之前,通过监听器机制加载数据、更新数据。

4、在容器初始化过程追加其他功能,输出日志、统计时间。

ManagerApplication启动类的main方法的静态run()方法:【10】SpringApplication.run(ManagerApplication.class, args); 
# 启动类名称、启动类参数

SpringApplication【1215】--> return run(new Class<?>[] { primarySource }, args); # 加载bean的优先级
	SpringApplication【1226】--> return new SpringApplication(primarySources).run(args);

	# 加载各种配置信息并初始化各种配置对象
	SpringApplication【1226】--> SpringApplication(primarySources)
		SpringApplication【253】--> this(null, primarySources);
				SpringApplication【267】--> public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources)
						# 资源加载器
						SpringApplication【268】-->this.resourceLoader = resourceLoader; 
						SpringApplication【269】-->Assert.notNull(primarySources, "PrimarySources must not be null");
						# 初始化配置类的类名信息(格式转换)
						SpringApplication【270】-->this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
						# 确认当前容器加载的类型
						SpringApplication【271】-->this.webApplicationType = WebApplicationType.deduceFromClasspath();
						# 获取ApplicationContextInitializer.class对象的实例
						SpringApplication【272】-->setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
						# 初始化监听器对初始化过程和运行过程进行干预
						SpringApplication【273】-->setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
						# 初始化引导类的类名信息
						SpringApplication【274】-->this.mainApplicationClass = deduceMainApplicationClass();

	# 初始化容器,得到ApplicationContext对象
	SpringApplication【1226】--> new SpringApplication(primarySources).run(args);
		# 设置计时器
		SpringApplication【299】-->StopWatch stopWatch = new StopWatch();
		# 计时器启动
		SpringApplication【300】-->stopWatch.start();
		# 系统引导信息对应的上下文对象,声明了ApplicationContext上下文对象
		SpringApplication【301】-->ConfigurableApplicationContext context = null;
		# 
		SpringApplication【302】-->Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		# 模拟输入输出信号,避免因出现缺少外设导致信号传输失败,进而引发错误(模拟显示器、键盘、鼠标等)
		SpringApplication【303】-->configureHeadlessProperty();
		# 获取当前注册可运行的监听器
		SpringApplication【304】-->SpringApplicationRunListeners listeners = getRunListeners(args);
		# 监听器执行步骤
		SpringApplication【305】-->listeners.starting();
			# 获取参数
			SpringApplication【307】-->ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			# 将读取的数据加载成一个环境对象,用来描述信息
			SpringApplication【308】-->ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			# 做一个bean的环境配置
			SpringApplication【309】-->configureIgnoreBeanInfo(environment);
			# 启动图标
			SpringApplication【310】-->Banner printedBanner = printBanner(environment);
			# 创建ApplicationContext的容器对象,根据前期配置的容器类型进行判断并创建
			SpringApplication【311】-->context = createApplicationContext();
			# 设置启动模式
			SpringApplication【312】-->exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
			SpringApplication【313】-->new Class[] { ConfigurableApplicationContext.class }, context);
			# 对容器进行设置上下文、环境、参数
			SpringApplication【314】-->prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			# 刷新容器
			SpringApplication【315】-->refreshContext(context);
			# 刷新后所做的后处理操作
			SpringApplication【316】-->afterRefresh(context, applicationArguments);
			# 计时器停止
			SpringApplication【317】-->stopWatch.stop();
			# 判断是否记录启动时间的日志
			if (this.logStartupInfo) {
			# 创建启动日志对象,输出日志信息、包括启动时间	
			SpringApplication【319】-->new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			# 监听器执行步骤	
			SpringApplication【321】-->listeners.started(context);
			# 容器的运行器 	
			SpringApplication【322】-->callRunners(context, applicationArguments);
			# 监听器执行步骤	
			SpringApplication【330】-->listeners.running(context);

总结:(面试中回答)

@SpringBootApplication  xxxApplication引导类的启动函数

  • @ SpringBootConfiguration = @Configuration ; @SpringBootConfiguration 是springboot启动函数的一个配置
  • @ComponentScan 是组件扫描 @RestController @Service @Mapper ...

excludeFilters - 扫描时加一个过滤器,用来在组件扫描时进行排除,也会排除自动配置类

  • @EnableAutoConfiguration  在META-INF/spring.factories中找xxxAutoConfiguration配置类
  • @AutoConfigurationPackage - 用来记住标注的类扫描的起始包名 工具类AutoConfigurationPackages.get(context.getDefaultListableBeanFactory())
  • @Import(AutoConfigurationImportSelector.class)分离主从配置实现弱耦合; 用来加载META-INF/spring.factories中的自动配置类;DeferredImportSelector推迟Import解析工作。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Husp0707

你的小小点赞、关注是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值