自动化配置是怎么实现的 - starter
对,但-这里边有一个非常关键的点,那就是条件注解
条件注解并非一个新事物,这是一个存在于 Spring 中的东西,
我们在 Spring 中常用的 profile 实际上就是条件注解的一个特殊化
核心思想就是当满足某种条件的时候,某个 Bean 才会生效,而正是这一特性,支撑起了 Spring Boot 的自动化配置
spring中条件注解的用法
首先创建一个maven项目
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
</dependencies>
定义一个接口 然后写2个实现类
public interface Food {
String showName();
}
public class Rice implements Food {
public String showName() {
return "米饭";
}
}
public class Noodles implements Food {
public String showName() {
return "面条";
}
}
再创建实现类的条件类
意思很简单
实现Condition 重写里面的 match方法 做条件属性判断
public class NoodlesCondition implements Condition {
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return conditionContext.getEnvironment().getProperty("people").equals("北方人");
}
}
public class RiceCondition implements Condition {
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return conditionContext.getEnvironment().getProperty("people").equals("南方人");
}
}
哪个条件得到满足,一会就会创建哪个 Bean
接下来就配置实现了
@Configuration
public class JavaConfig {
@Bean("food")
@Conditional(RiceCondition.class)
Food rice(){
return new Rice();
}
@Bean("food")
@Conditional(NoodlesCondition.class)
Food noodles(){
return new Noodles();
}
}
需要注意的是
- 两个 Bean 的返回值都为其父类对象 Food
- 当 @Conditional 注解中配置的条件类的 matches 方法返回值为 true 时,对应的 Bean 就会生效
测试
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext();
acac.getEnvironment().getSystemProperties().put("people","南方人");
acac.register(JavaConfig.class);
acac.refresh();
Food food = (Food) acac.getBean("food");
System.out.println(food.showName());
}
}
没错 - 南方人对应返回输出 米饭
进化写法
- 不再需要Condition类
- 把 @Conditional()注解改为@Profile()注解,里面写条件就行了
@Configuration
public class JavaConfig {
@Bean("food")
@Profile("南方人")
Food rice(){
return new Rice();
}
@Bean("food")
@Profile("北方人")
Food noodles(){
return new Noodles();
}
}
这样看起来 @Profile 注解貌似比 @Conditional 注解还要方便,那么 @Profile 注解到底是什么实现的呢?
点开来看看
可以看到 @Profile() 里面也是有 @Conditional()注解 的
看到这里就明白了,其实还是我们在条件注解中写的那一套东西,只不过 @Profile 注解自动帮我们实现了而已。
@Profile 虽然方便,但是不够灵活,因为具体的判断逻辑不是我们自己实现的。
而 @Conditional 则比较灵活