@ConditionalOnBean、@ConditionalOnProperty、@ConditionalOnClass、@Conditional和Condition接口的使用

亦凉 2022-11-12 02:54 296阅读 0赞

一、@ConditionalOnBean、@ConditionalOnProperty、@ConditionalOnClass

@ConditionalOnBean是指当spring容器中有某个bean时才装配。@ConditionalOnMissingBean当spring容器中不存在某个bean时才装配

@ConditionalOnClass是指当classpath下有某个类时才装配。@ConditionalOnMissingClass是指当classpath下没有某个类时才装配

@ConditionalOnProperty是指当某个配置项为某个值时才装配。@ConditionalOnMissingProperty是指当某个配置项不等于某个值时才装配

例如:@ConditionalOnBean(name=”user”)表示当容器中有名字为user的bean时才装配。

下面做下验证测试:

第一步:当没有任何注解时,spring容器里会有三个Runnable类型的bean,名字分别为createRable1,createRable2,createRable3

  1. package com.lsl;
  2. import org.springframework.boot.SpringBootConfiguration;
  3. import org.springframework.context.annotation.Bean;
  4. @SpringBootConfiguration
  5. public class MyConfig {
  6. @Bean
  7. public Runnable createRable1(){
  8. System.out.println("=======default======");
  9. return ()->{};
  10. }
  11. @Bean
  12. public Runnable createRable2(){
  13. System.out.println("=======dev======");
  14. return ()->{};
  15. }
  16. @Bean
  17. public Runnable createRable3(){
  18. System.out.println("=======user======");
  19. return ()->{};
  20. }
  21. }
  22. package com.lsl;
  23. import org.springframework.boot.SpringApplication;
  24. import org.springframework.boot.autoconfigure.SpringBootApplication;
  25. import org.springframework.context.ConfigurableApplicationContext;
  26. @SpringBootApplication
  27. public class SpringbootProviderApplication {
  28. public static void main(String[] args) {
  29. ConfigurableApplicationContext content = SpringApplication.run(SpringbootProviderApplication.class, args);
  30. System.out.println("springname=" + content.getEnvironment().getProperty("springboot.name"));
  31. System.out.println("ds.name=" + content.getEnvironment().getProperty("ds.name"));
  32. System.out.println("ds.password=" + content.getEnvironment().getProperty("ds.password"));
  33. //从容器中获取类型为Runnable的所有bean
  34. System.out.println(content.getBeansOfType(Runnable.class));
  35. }
  36. }

输出结果:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Roa2xzbA_size_16_color_FFFFFF_t_70

第二步:当分别加上注解时

  1. package com.lsl;
  2. import org.springframework.boot.SpringBootConfiguration;
  3. import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  5. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  6. import org.springframework.context.annotation.Bean;
  7. @SpringBootConfiguration
  8. public class MyConfig {
  9. @Bean
  10. @ConditionalOnBean(name="user")
  11. public Runnable createRable1(){
  12. System.out.println("=======default======");
  13. return ()->{};
  14. }
  15. @Bean
  16. @ConditionalOnClass(name="user")
  17. public Runnable createRable2(){
  18. System.out.println("=======dev======");
  19. return ()->{};
  20. }
  21. @Bean
  22. @ConditionalOnProperty(name="opFlag",havingValue = "save")
  23. public Runnable createRable3(){
  24. System.out.println("=======user======");
  25. return ()->{};
  26. }
  27. }

结果输出:由于没有user的bean所以没有装配

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Roa2xzbA_size_16_color_FFFFFF_t_70 1

第三步:创建User类,并交给spring容器托管。

  1. package com.lsl;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class User {
  5. }

输出结果:由于spring容器托管了User类,名字且为user,所以createRable1装配了

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Roa2xzbA_size_16_color_FFFFFF_t_70 2

在默认配置文件加上配置项 ,createRable3也装配了

20210322171152359.png

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Roa2xzbA_size_16_color_FFFFFF_t_70 3

由于classpath下没有user的bean,所有createRable2没有被装配。

二、@Conditional和Condition接口

上面的三个注解时spring提供的比较常用的几个注解,当然spring还提供了其他类似注解,

比如@ConditionalOnJava,当jdk为某个版本时才装配。

除此之外spring还提供了扩展,利用Condition接口和@Conditional注解自定义扩展功能

一般情况下Condition接口和@Conditional注解要配合使用。

首先是实现Condition接口。

  1. package com.lsl;
  2. import org.springframework.context.annotation.Condition;
  3. import org.springframework.context.annotation.ConditionContext;
  4. import org.springframework.core.type.AnnotatedTypeMetadata;
  5. import java.util.Arrays;
  6. import java.util.List;
  7. public class MyCondition implements Condition {
  8. @Override
  9. public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
  10. String opFlag = conditionContext.getEnvironment().getProperty("opFlag");
  11. String[] beanDefinitionNames = conditionContext.getRegistry().getBeanDefinitionNames();
  12. List<String> strings = Arrays.asList(beanDefinitionNames);
  13. if (strings.contains("user" ) && "save".equals(opFlag)){
  14. return true;
  15. }
  16. return false;
  17. }
  18. }

createRable4()方法上加了 @Conditional(MyCondition.class)注解,表示只有当MyCondition中的方法返回true时才装配。

  1. package com.lsl;
  2. import org.springframework.boot.SpringBootConfiguration;
  3. import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  5. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Conditional;
  8. @SpringBootConfiguration
  9. public class MyConfig {
  10. @Bean
  11. @ConditionalOnBean(name="user")
  12. public Runnable createRable1(){
  13. System.out.println("=======default======");
  14. return ()->{};
  15. }
  16. @Bean
  17. @ConditionalOnClass(name="user")
  18. public Runnable createRable2(){
  19. System.out.println("=======dev======");
  20. return ()->{};
  21. }
  22. @Bean
  23. @ConditionalOnProperty(name="opFlag",havingValue = "save")
  24. public Runnable createRable3(){
  25. System.out.println("=======user======");
  26. return ()->{};
  27. }
  28. @Bean
  29. @Conditional(MyCondition.class)
  30. public Runnable createRable4(){
  31. System.out.println("=======MyCondition======");
  32. return ()->{};
  33. }
  34. }

输出结果如下:MyCondition的功能是当配置项opFlag=save且容器中已经注册了user名字的bean时才返回true

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Roa2xzbA_size_16_color_FFFFFF_t_70 4

这种配合使用的方法非常灵活,可以多看看Condition接口中matchs方法的两个参数,这2个参数能获取好多信息,可以根据信息进行相关逻辑判断是返回true还是false.

发表评论

表情:
评论列表 (有 0 条评论,296人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Condition接口记录

    Condition接口常用方法         condition可以通俗的理解为条件队列。当一个线程在调用了await方法以后,直到线程等待的某个条件为真的时候才会被唤醒。

    相关 Condition接口

    Condition的作用是替代Object的监视器方法监视器方法(wait、notify 和 notifyAll),其主要是与Lock配合使用。