zoukankan      html  css  js  c++  java
  • springboot根据不同的条件创建bean,动态创建bean,@Conditional注解使用

     

    这个需求应该也比较常见,在不同的条件下创建不同的bean,具体场景很多,能看到这篇的肯定懂我的意思。

    倘若不了解spring4.X新加入的@Conditional注解的话,要实现不同条件创建不同的bean还是比较麻烦的,可能需要硬编码一些东西做if判断。那么现在有个@Conditional注解后,事情就简单多了。用法很简单,直接上代码。

    新建一个springboot项目,添加一个Configuration标注的类,我们通过不同的条件表达式来创建bean。

    1.  
      package com.tianyalei.condition;
    2.  
       
    3.  
      import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
    4.  
      import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    5.  
      import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
    6.  
      import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    7.  
      import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    8.  
      import org.springframework.context.annotation.Bean;
    9.  
      import org.springframework.context.annotation.Conditional;
    10.  
      import org.springframework.context.annotation.Configuration;
    11.  
       
    12.  
      /**
    13.  
      * Created by wuweifeng on 2017/10/11.
    14.  
      */
    15.  
      @Configuration
    16.  
      public class Config {
    17.  
       
    18.  
      @Conditional(MyCondition.class)
    19.  
      @Bean
    20.  
      public String condition() {
    21.  
      System.err.println("自定义的condition的match方法返回值为true时,才会进入该方法创建bean");
    22.  
      return "";
    23.  
      }
    24.  
       
    25.  
      /**
    26.  
      * 该Abc class位于类路径上时
    27.  
      */
    28.  
      @ConditionalOnClass(Abc.class)
    29.  
      @Bean
    30.  
      public String abc() {
    31.  
      System.err.println("ConditionalOnClass true");
    32.  
      return "";
    33.  
      }
    34.  
       
    35.  
      // @ConditionalOnClass(Abc.class)
    36.  
      // @Bean
    37.  
      // public Abc newAbc() {
    38.  
      // System.err.println("ConditionalOnClass true");
    39.  
      // return new Abc();
    40.  
      // }
    41.  
       
    42.  
      /**
    43.  
      * 存在Abc类的实例时
    44.  
      */
    45.  
      @ConditionalOnBean(Abc.class)
    46.  
      @Bean
    47.  
      public String bean() {
    48.  
      System.err.println("ConditionalOnBean is exist");
    49.  
      return "";
    50.  
      }
    51.  
       
    52.  
      @ConditionalOnMissingBean(Abc.class)
    53.  
      @Bean
    54.  
      public String missBean() {
    55.  
      System.err.println("ConditionalOnBean is missing");
    56.  
      return "";
    57.  
      }
    58.  
       
    59.  
      /**
    60.  
      * 表达式为true时
    61.  
      */
    62.  
      @ConditionalOnExpression(value = "true")
    63.  
      @Bean
    64.  
      public String expresssion() {
    65.  
      System.err.println("expresssion is true");
    66.  
      return "";
    67.  
      }
    68.  
       
    69.  
      /**
    70.  
      * 配置文件属性是否为true
    71.  
      */
    72.  
      @ConditionalOnProperty(
    73.  
      value = {"abc.property"},
    74.  
      matchIfMissing = false)
    75.  
      @Bean
    76.  
      public String property() {
    77.  
      System.err.println("property is true");
    78.  
      return "";
    79.  
      }
    80.  
      }

    这里面有个空类Abc.class,你可以就创建个叫Abc的类,里面是空的就行。

    1.  
      import org.springframework.context.annotation.Condition;
    2.  
      import org.springframework.context.annotation.ConditionContext;
    3.  
      import org.springframework.core.type.AnnotatedTypeMetadata;
    4.  
       
    5.  
      /**
    6.  
      * Created by wuweifeng on 2017/10/11.
    7.  
      */
    8.  
      public class MyCondition implements Condition {
    9.  
      @Override
    10.  
      public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
    11.  
      //判断当前系统是Mac,Windows,Linux
    12.  
      return conditionContext.getEnvironment().getProperty("os.name").contains("Mac");
    13.  
      }
    14.  
      }

    @Conditional(MyCondition.class)
    这句代码可以标注在类上面,表示该类下面的所有@Bean都会启用配置
    也可以标注在方法上面,只是对该方法启用配置


    除了自己自定义Condition之外,Spring还提供了很多Condition给我们用
    @ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
    @ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
    @ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
    @ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
    @ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
    @ConditionalOnNotWebApplication(不是web应用)

    以上是一些常用的注解,其实就是条件判断,如果为true了就创建Bean,为false就不创建,就这么简单。

    这些注解里的条件可以是多个,也可以赋默认值,也可以标注在类上,如果标注在类上,则对类里的所有@Bean方法都生效。

    其中@ConditionalOnProperty是指在application.yml里配置的属性是否为true,其他的几个都是对class的判断。

    我在配置里加上abc.property = true这个配置就可以测试上面的代码了。

    然后再来一个对类进行多个条件标注的例子:

    1.  
      package com.tianyalei.condition;
    2.  
       
    3.  
      import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    4.  
      import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    5.  
      import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    6.  
      import org.springframework.context.annotation.Bean;
    7.  
      import org.springframework.context.annotation.Configuration;
    8.  
       
    9.  
      /**
    10.  
      * Created by wuweifeng on 2017/10/11.
    11.  
      */
    12.  
      @Configuration
    13.  
      @ConditionalOnProperty(
    14.  
      value = {"abc.property"},
    15.  
      matchIfMissing = false
    16.  
      )
    17.  
      @ConditionalOnClass(Abc.class)
    18.  
      public class Multi {
    19.  
      @Bean
    20.  
      @ConditionalOnMissingBean({Abc.class})
    21.  
      public String check() {
    22.  
      System.err.println("multi check");
    23.  
      return "check";
    24.  
      }
    25.  
      }
    OK,代码很简单,运行看看结果

    可能上面的那些你用的地方不常见,那我来举一个我正在使用的例子。我的应用是基于SpringCloud的,在线上部署时有eureka来做注册中心,而在本地环境下,我的应用是单机的,不需要eureka,但是代码里已经引入了eureka了,每次启动就会自动去连接eureka,然后控制台就开始报错。虽然不影响功能,但是看着一直不停的报错也是不顺眼。

    那么我就可以使用Condition注解来解决它。

    1.  
      /**
    2.  
      * @author wuweifeng wrote on 2017/11/25.
    3.  
      * 根据部署环境动态决定是否启用eureka
    4.  
      */
    5.  
      @Component
    6.  
      @ConditionalOnProperty(value = "open.eureka")
    7.  
      @EnableDiscoveryClient
    8.  
      public class JudgeEnableDiscoveryClient {
    9.  
      }
    我把EnableDiscoveryClient这个注解单独放个类里,里面什么也不写,条件就是application.yml里配置的open.eureka
    如果我只想让线上的环境开启eureka,那么我就在application-prod.yml里配上open.eureka=true,其他的yml什么也不写就行了。这样本地启动时就相当于没有开启EnableDiscoveryClient。

    使用场景还是蛮多的,具体的看情况,但是需要记住有这么个注解,以便不时之需。

  • 相关阅读:
    prtg
    java实现第六届蓝桥杯穿越雷区
    java实现第六届蓝桥杯穿越雷区
    java实现第六届蓝桥杯穿越雷区
    java实现第六届蓝桥杯穿越雷区
    java实现第六届蓝桥杯穿越雷区
    java实现第六届蓝桥杯显示二叉树
    java实现第六届蓝桥杯显示二叉树
    java实现第六届蓝桥杯显示二叉树
    java实现第六届蓝桥杯显示二叉树
  • 原文地址:https://www.cnblogs.com/pejsidney/p/9273577.html
Copyright © 2011-2022 走看看