1:在上一篇文章中,我们大致能知道自定义的starter的配置类是如何被SpringBoor找到并且解析的,但是SpringBoot还会对这些配置类进行过滤,比如:当你配置了某些属性的时候这个配置类才会生效,当某个Bean存在这个配置类才生效,那么底层原理是怎么样的呢??
2:定义一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(MyCondition.class)
public @interface MyConditionOnProperty {
String value() default "";
}
3:实现MyCondition.class
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String value = (String) metadata.getAnnotationAttributes("com.leader.test.MyConditionOnProperty")
.get("value");
if(StringUtils.isEmpty(context.getEnvironment().getProperty(value))) {
return false;
}
return true;
}
}
4:动手测试:创建一个A类,
@Component
@MyConditionOnProperty(value = "coco")
public class A {
}
5:现在我们来测试下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootTestCo implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Test
public void test() {
A contextBean = applicationContext.getBean(A.class);
System.out.println(contextBean);
}
}
6:通过前面的例子你也许会发现@Condition前缀的注解的大概原理了,我们挑几个@ConditionalOnProperty,@ConditionalOnBean。我们看下这个注解的构造
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {}
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {}
是的,注解只有一个作用,那就是标志,而真正的处理逻辑就是在@Condition注解里面的实现类
7:总结
SpringBoot中@ConditionalOnProperty,@ConditionalOnBean等等之类的注解,都会有一个相关逻辑处理的类,
而这个类就是这个注解上@Condition注解中包含的那个类,这个类呢会实现Condition接口,即使这个类没有实现,那么它的父类也会实现,
实现这个类就会实现
public final boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {}
这个方法,比如@ConditionalOnProperty注解,机会判断SpringBoot中是否存在某个配置,如果存在就会返回true,
如果不存在就返回false,而我们上一篇文章是否会被解析也就是根据这个方法来进行判断的,返回true那就解析,
返回false,那就不解析