结构说明hello-spring-boot-starter: 没什么用,引用了autoconfigure模块
hello-spring-boot-starter-autoconfigure: 主要的自定义的starter模块
hello-spring-boot-web-demo: web模块
详情可以看:入门SpringBoot自定义starter
1、@Conditional注解的说明
@Conditional是Spring4.0出现的新特性,他可以选择性的创建Bean。
判断是否满足当前条件,如果满足则创建Bean,不满足则不创建
2、思路
根据说明可以了解到,@Conditional的作用是判断是否满足当前条件,如果满足则创建Bean,不满足则不创建
我们的思路是看看web模块是否能够注入starter提供的Bean
1、如果条件满足则成功创建,通过接口能成功拿到返回值
2、如果条件满足则成功创建,通过接口不能拿到返回值
2、autoconfigure模块
根据上次的自定义starter直接创建一个Bean
3、@Conditional的使用
3.1、SpringBoot是如何实现这个功能的
这是DispatcherServlet的自动注册配置类:
@Conditional接口是说如果DispatcherServletRegistrationCondition满足条件才会去配置
看下它的继承关系图:
顶层也是一个Condition的接口,然后SpringBoot自己去封装了Condition的模块方法。
你不信可以去看看其他的,比如Redis的相关配置,也会发现都是继承SpringBootCondition。
所以我们可以得出结论:
1、实现Condition接口并重写matches方法
2、继承SpringBootCondition抽象类并重写getMatchOutcome方法
3.2、造轮子
跟着SpringBoot的思路,我们去实现第一种:实现Condition接口并重写matches方法。
如果返回值为true则@Conditional则认为符合条件
Condition的编写
public class WindowCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// todo 拿配置文件的信息
return true;
}
}
Service的编写
public interface CmdService {
String print(String cmd);
}
public class WindowCmdService implements CmdService {
@Override
public String print(String cmd) {
return "window cmd ...";
}
}
自动配置类
public class CmdServiceConditionAutoConfiguration {
/**
* 当WindowCondition方法中的matches返回true的时候,
* WindowCmdService会被注入,否则不注入。
*/
@Bean
@Conditional(WindowCondition.class)
public WindowCmdService windowComService(){
return new WindowCmdService();
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mecuros.springboot.custom.starter.CmdServiceConditionAutoConfiguration
4、验证
在web模块引入starter并写出Controller接口
@RestController("/conditional")
public class ConditionalController {
@Resource
private WindowCmdService windowCmdService;
@GetMapping("/window/{cmd}")
public String window(@PathVariable String cmd){
return windowCmdService.print(cmd);
}
}
4.1、不用@Conditional的情况
不用@Conditional注解默认会创建WindowService
image.png
4.2、用@Conditional的情况
4.2.1、WindowConditional为true时
一切正常
image.png
4.2.2、WindowConditional为false时
image.png
image.png
5、总结
我们发现:
当Conditional为false,SpringBoot会报错。
当Conditional为true,接口正常。
证明:@Conditional注解需要配合两种方法使用
1、实现Condition接口并重写matches方法
2、继承SpringBootCondition抽象类并重写getMatchOutcome方法
并且在自动配置那里配合@Bean来一起使用。
6、其他知识点(待验证,后面会继续验证)
@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项