SpringBoot自定义配置类及自动配置基本原理
@SpringBootApplication注解
@Target({ElementType.TYPE}) //注解适用范围,如常用的TYPE(类和接口)、FIELD(字段)、METHOD(方法)、PARAMETER(参数)、ANNOTATION_TYPE(注解)等
@Retention(RetentionPolicy.RUNTIME) //注解的生命周期,如SOURCE(只存在编译期,编译结束后无该注释信息)、CLASS(默认,存在.class文件中)、RUNTIME(存在类文件中,且允许JVM读入)
@Documented //是否包含在用户文档中
@Inherited //注解继承与哪个注解类
@SpringBootConfiguration // 继承了Configuration注解,表示当前是一个配置类
@EnableAutoConfiguration // 开启自动配置功能,借助@import加载配置类
@ComponentScan( //扫描路径设置
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
..
}
@EnableAutoConfiguration注解
该注解主要由@Import({AutoConfigurationImportSelector.class})和AutoConfigurationPackage两个注解构成
第一个注解主要是将配置类自动加载到spring容器中,AutoConfigurationImportSelector实现了ImportSelector接口,自动调用selectImports方法,调用其内部方法getCandidateConfigurations读取classpath位置在META-INF/spring.factories中的文件内容,找到EnableAutoConfiguration对应类名的类加入到容器,另外在加载对应配置类时(通常配置类有@Configuration注解和其它条件注解)通过Conditional条件注解来加载满足条件类
AutoConfigurationPackage注解的作用是将添加该注解的类所在的package作为 自动配置package进行管理,如SpringBoot应用启动时默认会将启动类所在的package作为自动配置的package
@Import加载bean的三种方式
直接导入A类如@Import(A.class)
实现ImportSelector接口,根据接口返回的类全限定名导入,如@import(SelfImportSelector.class),该SelfImportSelector.class实现了ImportSelector接口
同上一样实现ImportBeanDefinitionRegistrar 接口,但接口中通过注册beanDefinition进行导入
配置类常用注解
- @Configuration 表示一个配置类,形如xml给容器添加组件
- @EnableConfigurationProperties(xxxProperties.class) 使指定的xxxProperties类生效,并加入到容器;另外@ConfigurationProperties可以将配置文件中对应的值和xxxProperties类中的属性进行绑定
- @ConditionalOnWebApplication 判断当前应用是否为web应用,若是配置类生效
- @ConditionalOnClass(xxx.class) 当前项目中是否有xxx.class,若有才生效
- @ConditionalOnMissBean(xxx.class) 容器中没有这个xxx的bean才生效
- @ConditionalOnResource(resources=“classpath:jdbc.properties”) 类路径下指定配置文件才生效
- @ConditionalOnProperty(perfix=“xxx”,value=“enable”,matchIfMissing=true) 判断配置文件中是否存在某个属性值xxx.enabled;如果不存在,判断也是成立的,即不配置也是默认生效,即指定属性是否有指定值
手写一个springboot自动配置类
- 导入项目的相关依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
- 配置maven插件,将maven插件修改为maven-compiler-plugin,否则可能无法引入
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
- 添加一个properties类,来绑定配置文件
@Data
@ConfigurationProperties(prefix = "com.wsp.user")
public class WelcomeServiceProperties {
private String name = "wsp";
}
- 添加一个服务实现类;
@Data
public class WelcomeService {
private String name;
public String sayUserName(){
return "Welcome " + name + " Enter !";
}
}
- 添加一个自动配置类;
@Configuration
@EnableConfigurationProperties(WelcomeServiceProperties.class)
@ConditionalOnClass(WelcomeService.class)
@ConditionalOnProperty(prefix = "com.wsp.user",value = "enabled",matchIfMissing = true)
public class WelcomeServiceAutoConfiguration {
@Autowired
private WelcomeServiceProperties welcomeServiceProperties;
@Bean
@ConditionalOnMissingBean(WelcomeService.class)//当容器中无该Bean会进行自动配置
public WelcomeService welcomeService(){
WelcomeService welcomeService = new WelcomeService();
welcomeService.setName(welcomeServiceProperties.getName());
return welcomeService;
}
}
- 在META-INF下的spring.factories文件中配置以下内容
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.wsp.demo.service.impl.WelcomeServiceAutoConfiguration
- 本地打包maven install 并引入坐标,最后测试
<dependency>
<groupId>com.wsp</groupId>
<artifactId>auto-config-demo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
@SpringBootTest
class TrainApplicationTests {
@Autowired
WelcomeService welcomeService;
@Test
void contextLoads() {
System.out.println(welcomeService.sayUserName());
}
}