Springboot自动装配原理

2023-05-16

springboot配置文件的装配过程

1、springboot在启动的时候会加载主配置类,开启了@EnableAutoConfiguration。

2、@EnableAutoConfiguration的作用:

  • 利用AutoConfigurationImportSelector给容器导入一些组件。
  • 查看selectImports方法的内容,返回一个AutoConfigurationEntry
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
      annotationMetadata);
------
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
------
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}
  • 可以看到SpringFactoriesLoader.loadFactoryNames,继续看又调用了loadSpringFactories方法,获取META-INF/spring.factories资源文件
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
		String factoryTypeName = factoryType.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
	}

	private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		try {
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					String factoryTypeName = ((String) entry.getKey()).trim();
					for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
						result.add(factoryTypeName, factoryImplementationName.trim());
					}
				}
			}
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}

总结:将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;每一个xxxAutoConfiguration类都是容器中的一个组件,最后都加入到容器中,用来做自动配置,每一个自动配置类都可以进行自动配置功能

使用HttpEncodingAutoConfiguration来解释自动装配原理

/*
表名这是一个配置类,
*/
@Configuration(proxyBeanMethods = false)
/*
启动指定类的ConfigurationProperties功能,进入HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来,并把HttpProperties加入到ioc容器中
*/
@EnableConfigurationProperties(HttpProperties.class)
/*
spring底层@Confitional注解,根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效
此时表示判断当前应用是否是web应用,如果是,那么配置类生效
*/
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
/*
判断当前项目由没有这个类CharacterEncodingFilter,springmvc中进行乱码解决的过滤器
*/
@ConditionalOnClass(CharacterEncodingFilter.class)
/*
判断配置文件中是否存在某个配置:spring.http.encoding.enabled
如果不存在,判断也是成立的,
即使我们配置文件中不配置spring.http.encoding.enabled=true,也是默认生效的
*/
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

    //和springboot的配置文件映射
	private final HttpProperties.Encoding properties;

    //只有一个有参构造器的情况下,参数的值就会从容器中拿
	public HttpEncodingAutoConfiguration(HttpProperties properties) {
		this.properties = properties.getEncoding();
	}

    //给容器中添加一个组件,这个组件的某些值需要从properties中获取
	@Bean
	@ConditionalOnMissingBean//判断容器中是否有此组件
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}

	@Bean
	public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
		return new LocaleCharsetMappingsCustomizer(this.properties);
	}

	private static class LocaleCharsetMappingsCustomizer
			implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {

		private final HttpProperties.Encoding properties;

		LocaleCharsetMappingsCustomizer(HttpProperties.Encoding properties) {
			this.properties = properties;
		}

		@Override
		public void customize(ConfigurableServletWebServerFactory factory) {
			if (this.properties.getMapping() != null) {
				factory.setLocaleCharsetMappings(this.properties.getMapping());
			}
		}

		@Override
		public int getOrder() {
			return 0;
		}
	}
}

根据当前不同的条件判断,决定这个配置类是否生效!

总结:

​ 1、springboot启动会加载大量的自动配置类

​ 2、查看需要的功能有没有在springboot默认写好的自动配置类中

​ 3、查看这个自动配置类到底配置了哪些组件

​ 4、给容器中自动配置类添加组件的时候,会从properties类中获取属性

@Conditional:自动配置类在一定条件下才能生效

@Conditional扩展注解作用
@ConditionalOnJava系统的java版本是否符合要求
@ConditionalOnBean容器中存在指定Bean
@ConditionalOnMissingBean容器中不存在指定Bean
@ConditionalOnExpression满足SpEL表达式
@ConditionalOnClass系统中有指定的类
@ConditionalOnMissingClass系统中没有指定的类
@ConditionalOnSingleCandidate容器中只有一个指定的Bean,或者是首选Bean
@ConditionalOnProperty系统中指定的属性是否有指定的值
@ConditionalOnResource类路径下是否存在指定资源文件
@ConditionOnWebApplication当前是web环境
@ConditionalOnNotWebApplication当前不是web环境
@ConditionalOnJndiJNDI存在指定项
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Springboot自动装配原理 的相关文章

随机推荐

  • java 后台list转换成json向前台传值

    通常前台js需要对后台传过来的值进行解析 xff0c 如果后台向前台传入的是一个json串的话 xff0c js比较容易处理 后台 根据自己需求写一个list List lt Object gt list 61 assistAdpater
  • windows美化指南秒变mac风格

    windows美化指南秒变mac风格 现如今网络的发展 xff0c 几乎每个人都有了一台电脑 xff0c 随着时代的进步 xff0c 由原来的winxp到win7到win10再到现在的win11 xff0c 每个系统无论是从底层架构还是外观
  • shell中使用ssh批量重启关闭/etc/hosts中添加了的机器

    ssh批量关闭 etc hosts中添加了的机器 xff0c 可自行修改 span class token shebang important bin bash span span class token keyword while spa
  • Windows Terminal的oh-my-posh配置方案

    参考Tutorial Set up a custom prompt for PowerShell or WSL with Oh My Posh 1 安装字体 NerdFonts字体下载 本人选择DejaVuSanMono Nerd Font
  • PX4系统学习

    PX4系统学习 扑翼飞行器的硬件组成飞控板电调电调的分类 舵机 扑翼飞行器的硬件组成 要了解学会二次开发首先要知道 xff0c 手头的飞行器的硬件结构 以及各个部分的结构是有何种作用的 xff0c 这样才能在根本上了解编程逻辑 xff0c
  • Java歌手评分系统

    有五个评委 xff0c 对一个歌手唱歌打分 xff0c 最终得分要求去掉最高分去掉最低分 xff0c 求平均分 注意要求的格式为 xff1a 输入第1个评委给分 97 1 输入第2个评委给分 89 2 输入第3个评委给分 88 6 输入第4
  • Linux 生产者消费者问题代码实现

    进程间通信 Linux xff1a 使用多线程和信号量解决生产者 消费者问题 xff1a 有一个长度为N的缓冲池被生产者和消费者共同使用 只要缓冲池未满 xff0c 生产者就可以将消息送入缓冲池中 xff1b 只要缓冲池不空 xff0c 消
  • Nocas单机启动命令

    之前在Linux中单机启动Nocas使用命令 xff1a sh startup sh m standalone 但是在cmd窗口使用该命令不行 xff0c 因为sh命令是在Linux系统中的文件 xff1b 而在本机cmd窗口运行Nocas
  • 项目中的resources目录中新建yml或properties文件,但是启动项目,没有读取到配置文件中的配置

    我的文件的图标显示这样 xff0c 说明SpringBoot加载时没有加载这个文件 1 查看yml properties文件中的内容是否有错 2 重启idea重启项目 3 手动设置该文件夹和文件为Spring的配置文件 右击resource
  • 二维数组的子数组之和的最大值

    对于一维的数组 xff0c 要求其子数组之和的最大值很简单 xff0c 动态规划轻松解决 xff0c 复杂度O N span style background color rgb 255 255 255 font family none f
  • MySQL错误ERROR 1046 (3D000): No database selected解决办法

    No database selected可以理解为没有选择种数据库 先在查看数据库种包括的database有哪些 xff0c 选择自己要操作的数据 记住database后面一定加s 选择自己要操作那一个数据库 这样选择之后mysql gt
  • CentOS7使用su命令切换到root用户:su:鉴定故障

    安装完CentOS7后 xff0c 在设置过程中设置了root密码 xff0c 但是当从普通用户切换到root用户时报错 这时就想到可以将系统模式切换到单用户模式下 xff0c 修改root密码 重启CentOS7系统 xff0c 按e键
  • CentOS7版本设置系统的静态IP地址

    每次CentOS7重新开机 xff0c 系统的IP地址都会改变 xff0c 使用起来很不方便 xff0c 所以就将系统的IP设置为静态不变的IP 首先需要找到CentOS7版本的网络配置文件在哪里 xff0c 版本不一样可能配置文件不一样
  • “Job for docker.service failed because the control process exited with error code.” 问题解决

    前一天使用Docker还可以 xff0c 第二天使用systemctl start docker命令启动 xff0c 结果 我找问题花了两个小时 xff0c 在哪里一通乱找 xff0c 一通乱查 xff0c 网上乱看博客 xff0c 浪费了
  • RocketMQ同一Topic、消费组创建多个消费者失败问题

    文章目录 业务场景问题复现解决方式问题跟踪 业务场景 rocketmq建议一个服务对应一个topic xff0c 但是一个服务下会有多个不同的业务消息 xff0c 同时rocketmq建议不同的业务消息对应不同的tag xff0c 当Spr
  • AD18设计PCB时常见问题及操作

    我做PCB设计时 xff0c 常采用AD18这个软件 xff0c 使用过程中经常碰到一些问题 xff0c 遇到查了半天解决了 后来又碰到了 xff0c 索性记一下吧 xff0c 以后碰到的也陆陆续续记上来 xff0c 图片不一定用自己的了
  • C/C++中的new和delete的实现过程

    文章目录 newdeletenew delete 下面是 C 43 43 Primer 5th 中P726 对 new 和 delete 过程的解释 xff1a 当我们使用一条new表达式时 xff0c 实际上执行了三步操作 xff1a n
  • 判断链表是否有环

    题目 xff1a 给你一个链表的头节点 head xff0c 判断链表中是否有环 如果链表中有某个节点 xff0c 可以通过连续跟踪 next 指针再次到达 xff0c 则链表中存在环 为了表示给定链表中的环 xff0c 评测系统内部使用整
  • Linux 我已经搭建好LAMP,怎么让别人访问到我的服务器(通过外网),端口映射,内网穿透

    使用Ngrok 免费 xff09 1 下载Ngrok https dashboard ngrok com get started setup 2 解压并移动到 usr bin mv ngrok usr bin 3 映射127 0 0 1 x
  • Springboot自动装配原理

    springboot配置文件的装配过程 1 springboot在启动的时候会加载主配置类 xff0c 开启了 64 EnableAutoConfiguration 2 64 EnableAutoConfiguration的作用 xff1a