1.自动装配的定义
自动装配是springboot的核心,一般提到自动装配就会和springboot联系在一起。实际上 Spring Framework 早就实现了这个功能。Spring Boot 只是在其基础上,通过 SPI 的方式,做了进一步优化。
没有 Spring Boot 的情况下,如果我们需要引入第三方依赖,需要手动配置,非常麻烦。但是,Spring Boot 中,我们直接引入一个 starter 即可。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
自动装配可以理解为:通过注解或配置就能在spring boot的帮助下快速实现某种功能。
Spring Boot的装配原理基于Spring框架,它使用一个@EnableAutoConfiguration
注解来启用自动配置功能,这允许Spring Boot根据类路径中的jar依赖项推断出应用程序所需的bean。
Spring Boot使用Spring框架的条件化配置功能,这允许它只创建在类路径中找到的相应bean。
以下是一个简单的例子,展示了如何使用Spring Boot的自动配置:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class, args);
}
}
在这个例子中,@SpringBootApplication
是一个组合注解,包含以下三个主要注解:
@Configuration
:表示该类以类的形式提供bean的配置。@ComponentScan
:启用组件扫描,这使得Spring Boot可以自动发现和装配其他配置类。@EnableAutoConfiguration
:开启Spring Boot的自动配置功能。
当Spring Boot应用程序启动时,它会自动根据类路径上的jar依赖项配置bean。例如,如果你的项目包含了spring-boot-starter-web
依赖,那么Spring Boot会自动配置Spring MVC和Tomcat等web应用程序的必需bean。
装配过程中,Spring Boot会读取application.properties
或application.yml
文件中的配置,以及任何使用@ConfigurationProperties
注解的配置类。
Spring Boot还提供了自定义自动配置的方式,可以通过编写自己的@Configuration
类,并使用@Conditional
注解来控制配置的条件。
@EnableAutoConfiguration:实现自动装配的核心注解
EnableAutoConfiguration
只是一个简单地注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector
类。
AutoConfigurationImportSelector
类实现了 ImportSelector
接口,也就实现了这个接口中的 selectImports
方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 Ioc 容器中
这里我们需要重点关注一下getAutoConfigurationEntry()
方法,这个方法主要负责加载自动配置类的。
现在我们结合getAutoConfigurationEntry()
的源码来详细分析一下:
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
//第1步:判断自动装配开关是否打开
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//第2步:用于获取注解中的exclude和excludeName。
//获取注解属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//第3步:获取需要自动装配的所有配置类,读取META-INF/spring.factories
//读取所有预配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//第4步:符合条件加载
//去掉重复的配置类
configurations = removeDuplicates(configurations);
//执行
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//校验
checkExcludedClasses(configurations, exclusions);
//删除
configurations.removeAll(exclusions);
//过滤
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
//创建自动配置的对象
return new AutoConfigurationEntry(configurations, exclusions);
}
Spring Boot 提供的条件注解如下:
@ConditionalOnBean:当容器里有指定 Bean 的条件下
@ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下
@ConditionalOnSingleCandidate:当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选 Bean
@ConditionalOnClass:当类路径下有指定类的条件下
@ConditionalOnMissingClass:当类路径下没有指定类的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径是否有指定的值
@ConditionalOnExpression:基于 SpEL 表达式作为判断条件
@ConditionalOnJava:基于 Java 版本作为判断条件
@ConditionalOnJndi:在 JNDI 存在的条件下差在指定的位置
@ConditionalOnNotWebApplication:当前项目不是 Web 项目的条件下
@ConditionalOnWebApplication:当前项目是 Web 项 目的条件下
最终可以得出,Spring Boot 通过@EnableAutoConfiguration开启自动装配,通过 SpringFactoriesLoader 最终加载META-INF/spring.factories中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional按需加载的配置类,想要其生效必须引入spring-boot-starter-xxx包实现起步依赖