深度解析Spring Boot自动装配

说到自动装配就要从Springboot的核心注解看起,即 @SpringBootApplication ;这是一个复合注解,是由
1、@Configuration:
@Configuration 这个注解大家应该都用过,它是 JavaConfig 形式的基于 Spring IOC 容器的配置类使用的一种注解。所以在启动类里面标注了 @Configuration,意味着它其实也是一个 IoC 容器的配置类。

传统意义上的 Spring 应用都是基于 xml 形式来配置 bean 的依赖关系。但是从 Spring3 开始,Spring 就支持了两种 bean 的配置方式,一种是基于 xml 文件方式,另一种就是 JavaConfig,任何一个标注了 @Configuration 的 Java 类定义都是一个 JavaConfig 配置类。而在这个配置类中,任何标注了 @Bean 的方法,它的返回值都会作为 Bean 定义注册到 Spring 的 IoC 容器,方法名默认成为这个 Bean 的 id。然后通过 spring 容器在启动的时候,把 Bean 进行初始化并且,如果 Bean 之间存在依赖关系,则分析这些已经在 IoC 容器中的 Bean 根据依赖关系进行组装。
2、@ComponentScan
@ComponentScan 这个注解大家也用过,这个很简单,就是扫包,相当于 xml 配置文件中的
context:component-scan 。它的主要作用就是扫描指定路径下的标识了需要装配的类,自 动装配到 Spring 的 IoC 容器中。

标识需要装配的类的形式主要是:@Component、@Repository、@Service、@Controller 这类的注解标识的类。(注:@Repository、@Service、@Controller 的底层还是 @Component)。ComponentScan 默认会扫描当前 package 下的的所有加了相关注解标识的类到 IoC 容器中。
3、@EnableAutoConfiguration:
@EnableAutoConfiguration 是 Spring Boot 的灵魂,是重中之重。从 Spring3.1 开始,提供了一系列的 @Enable 开头的注解,它是在 JavaConfig 框架上更进一步的完善,使用户在使用 Spring 相关的框架避免配置大量的代码从而降低使用的难度。如图:
在这里插入图片描述
比如常见的一些 Enable 注解:@EnableWebMvc、@EnableScheduling、@EnableAsync 等等。每一个涉及到 Enable 开头的注解,都会带有一个 @Import 的注解, @EnableAutoConfiguration 也不例外
@Import 注解是什么意思呢?它对应 XML 形式下的 ,就是导入资源,把多个分布在不同容器下的配置合并在一个配置中。@Import 注解可以配置三种不同的 class :

普通 Bean 或者带有 @Configuration 的配置文件
实现 ImportSelector 接口进行动态注入
实现 ImportBeanDefinitionRegistrar 接口进行动态注入
这里导入的是第二种 importSelector,这是一种动态注入 Bean 的技术,我们把 AutoConfigurationImportSelector 点进去,发现它实现了 ImportSelector 接口。如图:
在这里插入图片描述

找到实现方法 selectImports ,该方法的作用就是找到相应的 Bean 注入到容器中。

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

再从 getAutoConfigurationEntry 方法点进去,这里面做了许多事情,就是把找到的 Bean 进行排除、过滤、去重,我们可以看到 removeDuplicates、remove、filter 等方法。如图:
在这里插入图片描述那具体这些 Bean 从哪里找呢,我们将 getCandidateConfigurations 方法点进去,发现了一个惊天秘密,那就是在这有一个 META-INF/spring.factories 文件。
在这里插入图片描述
我们把 SpringFactoriesLoader.loadFactoryNames 点进去,发现这里有个变量 FACTORIES_RESOURCE_LOCATION。
在这里插入图片描述而这个变量的值还是 META-INF/spring.factories。
在这里插入图片描述原来 SpringFactoriesLoader 的作用就是从 classpath/META-INF/spring.factories 文件中,根据 key 来加载对应的类到 Spring IoC 容器中。
在这里插入图片描述看到这里小伙伴就明白了,就是把这么多 Configuration 下的 Bean 加载到容器里嘛。
但是
怎么还有 RabbitMQ、Elasticsearch 这些我都用不到,怎么也给加到容器里来了,那多浪费空间和内存啊?小伙伴莫慌,于是我又带着好奇心理打开了 RabbitMQ 的配置类。
在这里插入图片描述
看到这里终于舒了口气,小伙们有没有发现这里多了一些 Conditional 的注解,其实这些就是条件注解,Spring Boot 也不傻,它会发现如果当前的 classpath 环境下没有相关联的依赖,则意味着这些类没必要进行加载。所以,通过这种条件过滤可以有效的减少 @configuration 类的数量从而降低 Spring Boot 的启动时间。

Conditions	描述
@ConditionalOnBean	在存在某个 bean 的时候
@ConditionalOnMissingBean	不存在某个 bean 的时候
@ConditionalOnClass	当前 classpath 可以找到某个类型的类时
@ConditionalOnMissingClass	当前 classpath 不可以找到某个类型的类时
@ConditionalOnResource	当前 classpath 是否存在某个资源文件
@ConditionalOnProperty	当前 jvm 是否包含某个系统属性为某个值
@ConditionalOnWebApplication	当前 spring context 是否是 web 应用程序
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值