@Conditional注解
这个注解在Spring4中引入,其主要作用就是判断条件是否满足,从而决定是否初始化并向容器注册Bean
1. 定义
@Conditional注解定义如下,其内部主要就是利用了Condition接口,来判断是否满足条件,从而决定是否需要加载Bean
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
下面是Condtion接口的定义,这个可以说是最基础的入口了,其他的所有条件注解,归根结底,都是通过实现这个接口进行扩展的
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
这个接口中,有个参数比较有意思ConditionContext,它持有不少有用的对象,可以用来获取很多系统相关的信息,来丰富条件判断,接口定义如下
public interface ConditionContext {
// 获取Bean定义
BeanDefinitionRegistry getRegistry();
// 获取Bean工程,因此就可以获取容器中的所有bean
@Nullable
ConfigurableListableBeanFactory getBeanFactory();
// environment 持有所有的配置信息
Environment getEnvironment();
// 资源信息
ResourceLoader getResourceLoader();
// 类加载信息
@Nullable
ClassLoader getClassLoader();
}
2、如何使用Condition和@Conditional注解,来实现bean的条件加载,自动扫描Bean的条件加载
从使用来讲,和前面的没有什么区别,只是将注解放在具体的类上而言,同样给出一个示例,先定义一个bean
@Component
@Conditional(ScanDemoCondition.class)
public class ScanDemoBean {
@Value("${conditional.demo.load}")
private boolean load;
public boolean getLoad() {
return load;
}
}
对应的判断条件如下,当配置文件中conditional.demo.load为true时,才会加载这个配置,否则不实例化
public class ScanDemoCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return "true".equalsIgnoreCase(conditionContext.getEnvironment().getProperty("conditional.demo.load"));
}
}
测试类和前面差不多,稍微注意下的就是自动注入时,改一下必要条件,避免bean不存在时报错
@Autowired(required = false)
private ScanDemoBean scanDemoBean;
@GetMapping(path = "/scan")
public String showDemo() {
String type = environment.getProperty("conditional.demo.load");
if (scanDemoBean == null) {
return "not exists! >>>" + type;
} else {
return "load : " + scanDemoBean.getLoad() + " >>>" + type;
}
}
3、Spring框架提供了一系列相关的注解,如下表
| 注解 | 说明 |
|---|---|
@ConditionalOnSingleCandidate |
当给定类型的bean存在并且指定为Primary的给定类型存在时,返回true |
@ConditionalOnMissingBean |
当给定的类型、类名、注解、昵称在beanFactory中不存在时返回true.各类型间是or的关系 |
@ConditionalOnBean |
与上面相反,要求bean存在 |
@ConditionalOnMissingClass |
当给定的类名在类路径上不存在时返回true,各类型间是and的关系 |
@ConditionalOnClass |
与上面相反,要求类存在 |
@ConditionalOnCloudPlatform |
当所配置的CloudPlatform为激活时返回true |
@ConditionalOnExpression |
spel表达式执行为true |
@ConditionalOnJava |
运行时的java版本号是否包含给定的版本号.如果包含,返回匹配,否则,返回不匹配 |
@ConditionalOnProperty |
要求配置属性匹配条件 |
@ConditionalOnJndi |
给定的jndi的Location 必须存在一个.否则,返回不匹配 |
@ConditionalOnNotWebApplication |
web环境不存在时 |
@ConditionalOnWebApplication |
web环境存在时 |
@ConditionalOnResource |
要求制定的资源存在 |
@ConditionalOnExpression |
? 当表达式为true的时候,才会实例化一个Bean。 |
@ConditionalOnProperty 注解
@Configuration
public class WebConfig {
@Bean
@ConditionalOnProperty(prefix = "rest", name = "auth-open", havingValue = "true", matchIfMissing = true)
public AuthFilter jwtAuthenticationTokenFilter() {
return new AuthFilter();
}
}
- prefix:application.properties配置的前缀
- name:属性是从application.properties配置文件中读取属性值
- havingValue:配置读取的属性值跟havingValue做比较,如果一样则返回true,否则返回false;如果返回值为false,则该configuration不生效;为true则生效
- matchIfMissing = true:表示如果没有在application.properties设置该属性,则默认为条件符合
上面代码的意思:是否启动jwt的的配置,如果application.properties配置中没有设置就启动jwt,如果设置了true就启动,如果false就关闭。
application.properties 配置如下
rest:
auth-open: true # jwt鉴权机制是否开启(true或者false)