Spring boot自动装配,是指spring应用程序上下文,根据类路径,和定义的bean,猜测并自动装配该应用程序可能要用到的bean。
官方文档:https://docs.spring.io/spring-boot/docs/2.3.9.RELEASE/reference/html/using-spring-boot.html#using-boot
自动装配原理初探
pom.xml
- 核心依赖:在父工程spring-boot-dependencies中
- 引入spring-boot依赖时,不需要指定版本号,版本号统一在spring-boot-dependencies中管理。
- 引入插件时,若maven加载报错找不到,要指定版本号
启动器starter
starter启动器是一种零配置、开箱即用的spring生态内第三方配置库。就好比Spring生态内一站式技术解决方案商店。
启动器包含了应用正常运转所需的全部依赖。该依赖具有完整性,可传递性。
-
spring boot所有官方启动器都是以spring-boot-starter开头的,方便开发者搜索starter
-
比如spring-boot-starter-web,会自动导入web环境所有的依赖。
-
springboot会将所有的功能场景,配置并包装成一个个启动器。
-
需要使用什么功能,只需导入对应的启动器就可以了。
-
Spring官方支持的启动器列表详见:
https://docs.spring.io/spring-boot/docs/2.3.9.RELEASE/reference/html/using-spring-boot.html#using-boot-starter
主程序
主程序是启动Spring boot的入口。一般@SpringBootApplication 或者@EnableAutoConfiguration注解修饰的类,是Spring boot项目的主程序。主程序本身也是一个主配置类。
@SpringBootApplication //标注这是一个Spring boot应用程序,启动类下的所有资源被导入
public class Springboot01HelloApplication {
public static void main(String[] args) {
/*运行Spring boot应用程序*/
SpringApplication.run(Springboot01HelloApplication.class, args);
}
}
主程序要放在root package下面。用户自定义的包也要在root package下。以便conponent-scan
可以自动扫描跟主程序同级的包,自动装配成Spring bean。
@SpringBootApplication注解
@SpringBootApplication等价于@SpringBootConfiguration、@EnableAutoConfiguration、 @ComponentScan三个注解。
@SpringBootConfiguration
@Configuration //表明是一个配置类
@Conponent //注册为Spring的一个组件
@EnableAutoConfiguration
@AutoConfigurationPackage //自动配置包
@Import(AutoConfigurationPackages.Registrar.class) //自动配置包注册者
@Import(AutoConfigurationImportSelector.class) //自动配置导入选择器
@ComponentScan //自动扫描跟主程序同级的包
@Configuration注解
spring boot推荐基于java代码的配置java config。使用@Configuration注解修饰类,表示该类为一个配置类。同时也被标记为@Component
组件。
- 可以通过@Import注解引入其它@Configuration类。
proxyBeanMethods
属性- ture:full模式, 利用cglib代理增强,bean是单例的。SpringBoot启动会检查容器中是否存在该组件。
- false:lite模式,每一次调用,都返回新实例对象。SpringBoot启动时不会检查该组件,启动更快。
@Conditional组合注解
使用@Conditional
组合注解来指定自动加载bean的条件。@Conditional
指定的条件成立,才会在Application Context 中加载组件,自动配置类才生效。
- 作用在TYPE上,Spring 自动扫描的一切类 (@Configuration, @Component, @Service, @Repository, @Controller) 都可以通过添加相应的
@ConditionalOnXxxx
来判断是否自动加载到应用上下文。 - 作用在METHOD上,仅限于@Bean标记的方法。
@Conditional扩展注解 | 判断条件 |
---|---|
@ConditionalOnJava | 运行指定的Java版本 |
@ConditionalOnBean | 容器中存在指定Bean |
@ConditionalOnMissingBean | 容器中不存在指定Bean |
@ConditionalOnExpression | 满足指定的SpEL表达式,支持多个配置属性组合判断 |
@ConditionalOnClass | 类路径上有指定的类 |
@ConditionalOnMissingClass | 类路径上没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者有一个用@Primary指定的首选Bean |
@ConditionalOnProperty | properties或yaml文件中配置的指定属性是否有指定的值 |
@ConditionalOnResource | 类路径下是否有指定的资源文件 |
@ConditionalOnWebApplication | 当前应用是Web应用 |
@ConditionalOnNotWebApplication | 当前应用不是Web应用 |
@ConditionalOnJndi | 指定的资源通过 JNDI 加载 |
在配置文件中,配置debug属性值为true,即可在启动日志中,查看到已生效Positive match的bean,未生效Negative match的bean,以及排除在外Exclude的bean。
步骤
加载META-INF/spring.factories
配置文件
AutoConfigurationImportSelector
类getAutoConfigurationEntry()
方法中:
//获取所有配置
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
类loadSpringFactories()
:
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
......
}
自动配置核心文件FACTORIES_RESOURCE_LOCATION
:META-INF/spring.factories
,自动配置类在spring-boot-autoconfigure-2.4.3.jar
包下面。
- XXXAutoConfiguration:自动配置类,容器根据匹配条件,自动加载组件到应用上下文
- XXXProperties:用于装配配置文件中自定义的配置内容。
结论:
- Spingboot所有的自动配置都是在启动类中扫描并加载。
- 从classpath中搜寻
META-INF/spring.factories
配置文件,并将里面所有XXXAutoConfiguration配置项,通过反射,实例化为org.springframework.boot.autoconfigure
包下面的配置类,并纳入到IOC容器管理。 - 整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中。
- Spring boot自动配置机制,免去了我们手动编写配置注入依赖等工作。