前言
一个刚刚看完SpringBoot自动装配原理的萌新依据自己的理解写下的文章,如有大神发现错误,敬请斧正,不胜感激。
分析SpringBoot自动配置原理
- SpringBoot的启动从被@SpringBootApplication修饰的启动类开始,@SpringBootApplicaiotn注解中最重要的注解是@EnableAutoConfiguration,其负责自动装配,底层由@Import()注解中传入一个ImportSeletor的实现类AutoConfigurationImportSelector完成自动配置类的导入
- AutoConfigurationImportSelector类中selectImports方法负责返回一个由自动配置类权限定类名组成的字符串数组,在这个方法中扫描了spring-boot-autoconfigure-2.6.13.jar/WEB-INF/spring.factories中的所有权限定类名,经层层返回以及@Conditional系类的注解筛选后,将需要加载的配置交给IOC容器完成自动配置
一个标准的SpringBoot启动器的组成
一个“干活的”类
这个类是整个模块的核心,他完成整个模块中的逻辑操作,他的参数需要从配置文件中获取,他需要被纳入IOC容器的管理
一个"搬运工"类
这个类从配置文件中读取数据,并被注入到核心类中,是核心类从配置文件中获取数据的桥梁
一个"与SpringBoot沟通"的类
这个类的权限定类名被写入到spring-boot-autoconfigure-2.6.13.jar/WEB-INF/spring.factories文件中,在SpringBoot容器启动时被读取,并通过@Conditional系列注解判断是否加载该配置文件,以及将核心类纳入到IOC容器管理
自定义SpringBoot启动器
目标:完成一个自我介绍类,从配置文件中获取name以及introduction介绍词
搬运工类SelfIntroductionPropertis
@ConfigurationProperties(prefix = "self") // 指定配置文件中的前缀
@Data
public class SelfIntroductionPropertis {private String name = "Default Name";private String introduction = "Default Introduction";
}
@ConfigutationProperties(prefix=“self”)使用配置绑定对象完成对配置的读取
核心类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SelfIntroductionService {@Resourceprivate SelfIntroductionPropertis selfIntroductionProperties;public String say(){return "Hello,My name is" + selfIntroductionProperties.getName() + "," + selfIntroductionProperties.getIntroduction();}
}
- @Resource 自动注入SelfIntroductionPropertis对象
- say()方法完成该模块的主要功能
与"SpringBoot"沟通,完成自动装配的类
@EnableConfigurationProperties(SelfIntroductionPropertis.class)
//开启对SelfIntroductionPropertis类中@ConfigurationProperties注解的配置绑定支持,并将其纳入IOC容器管理
@ConditionalOnClass(SelfIntroductionService.class)
@Configuration // 是一个配置类,配置bean
public class SelfIntroductionAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic SelfIntroductionService selfIntroductionService() {return new SelfIntroductionService();}
}
- @EnableConfigurationProperties注解开启对SelfIntroductionPropertis类中@ConfigurationProperties注解的配置绑定支持,并将其纳入IOC容器管理
- @ConditionalOnClass(SelfIntroductionService.class)完成自动配置的关键,只有当核心类存在时才引入这个配置类
- @Bean 将SelfIntroductionService纳入IOC容器的管理,并指定name
将自动配置类加入到SpringBoot自动配置jar包中的WEB-INF/spring.factories中
从包中复制.factories文件到main/resource/WEB-INF文件夹下,使该自动配置类在SpringBoot启动时能被扫描到,完成自动配置
打包,并存入本地maven仓库
测试
新建SpringBoot工程并将自定义启动器引入
<?xml version="1.0" encoding="UTF-8"?>
<project>
。。。<dependencies><dependency><groupId>xyz.wrywebsite</groupId><artifactId>springboot-mystarted</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>
。。。</project>
配置文件编写
server.port=8080
self.name=lisi
self.introduction=wow wow wow
编写测试类
@RestController
public class BasicController {@Resourceprivate SelfIntroductionService selfIntroductionService;@GetMapping("/selfIntroduction")public String selfIntroduction() {return selfIntroductionService.say();}}
运行,输出结果
Hello,My name islisi,wow wow wow