如何使用SpringBootCondition更自由地定义条件化配置

Conditional如何使用

@Conditional 是 SpringFramework 的功能, SpringBoot 在它的基础上定义了 @ConditionalOnClass , @ConditionalOnProperty 的一系列的注解来实现更丰富的内容。

定义一个自定义标签

import com.example.conditional.MyConditional;
import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(MyConditional.class)
public @interface MyConditionalIAnnotation {
  String key();
  String value();
}

自定义Conditional

import com.example.conditional.interfaceI.MyConditionalIAnnotation;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Map;

public class MyConditional extends SpringBootCondition {

  @Override
  public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(MyConditionalIAnnotation.class.getName());
    Object key = annotationAttributes.get("key");//
    Object value = annotationAttributes.get("value");
    if(key == null || value == null){
      return new ConditionOutcome(false, "error");
    }

    //获取environment中的值
    String key1 = context.getEnvironment().getProperty(key.toString());
    if (value.equals(key1)) {
      //如果environment中的值与指定的value一致,则返回true
      return new ConditionOutcome(true, "ok");
    }
    return new ConditionOutcome(false, "error");

  }
}

config配置

import com.example.conditional.interfaceI.MyConditionalIAnnotation;
import com.example.conditional.service.MyConditionalService;
import org.apache.log4j.Logger;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConditionalConfig {
  public static Logger logger=Logger.getLogger(MyConditionalService.class);

  /**
   * 判断MyConditional 是否符合条件,是则运行MyConditionalService
   * @return
   */
  @MyConditionalIAnnotation(key = "com.example.conditional", value = "lbl")
  @ConditionalOnClass(MyConditionalService.class)
  @Bean
  public MyConditionalService initMyConditionService() {
    logger.info("MyConditionalService已加载。");
    return new MyConditionalService();
  }
}

配置文件:application.propeties

spring.application.name=gateway
server.port=8084
#conditional 动态配置,判断该值是否等于lbl,是则创建MyConditionalService实例
com.example.conditional=lbl
#支持自定义aop
spring.aop.auto=true

SpringBootCondition 定义条件化配置

1 条件化配置

Spring提供了多种实现化条件化配置的选择,如ConditionalOnProperty和ConditionalOnClass等。

用法如下:

@ConditionalOnProperty(prefix = "pkslow", name = "service", havingValue = "larry")

还有:

@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)

但有时候我们需要更灵活的自定义条件配置,这时可以通过继承SpringBootCondition类来实现。

2 继承SpringBootCondition

自己根据需求实现自己的判断逻辑,我的实现如下:

public class PkslowCondition extends SpringBootCondition {
 @Override
 public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
  BindResult<List<String>> maxBindResult = Binder.get(context.getEnvironment()).bind("pkslow.condition.max", Bindable.listOf(String.class));
  BindResult<List<String>> minBindResult = Binder.get(context.getEnvironment()).bind("pkslow.condition.min", Bindable.listOf(String.class));

  if ( (maxBindResult.isBound() && !maxBindResult.get().isEmpty()) && (minBindResult.isBound() && !minBindResult.get().isEmpty()) ) {
   List<String> maxs = maxBindResult.get();
   List<String> mins = minBindResult.get();
   int max = Integer.parseInt(maxs.get(0));
   int min = Integer.parseInt(mins.get(0));

   if (max < 1000 && min > 0) {
    return ConditionOutcome.match();
   }

  }

  return ConditionOutcome.noMatch("pkslow.condition.max/pkslow.condition.min not matches");
 }
}

表示需要有配置属性pkslow.condition.max/pkslow.condition.min才会生效,并且要求max<1000且min>0。

3 使用

完成自定义的条件类后,就可以使用它来限定一个配置类是否要生效了,使用如下:

@Conditional(PkslowCondition.class)
@Configuration
public class PkslowConfig {
  @PostConstruct
  public void postConstruct() {
    System.out.println("PkslowConfig called");
  }
}

4 总结

代码请查看:https://github.com/LarryDpk/pkslow-samples

以上就是如何使用SpringBootCondition更自由地定义条件化配置的详细内容,更多关于SpringBootCondition 定义条件化配置的资料请关注我们其它相关文章!

(0)

相关推荐

  • springboot @ConditionalOnMissingBean注解的作用详解

    @ConditionalOnMissingBean,它是修饰bean的一个注解,主要实现的是,当你的bean被注册之后,如果而注册相同类型的bean,就不会成功,它会保证你的bean只有一个,即你的实例只有一个,当你注册多个相同的bean时,会出现异常,以此来告诉开发人员. 代码演示 @Component public class AutoConfig { @Bean public AConfig aConfig() { return new AConfig("lind"); } @B

  • Spring Boot conditional注解用法详解

    1.conditional注解介绍 含义: 基于条件的注解 作用: 根据是否满足某一个特定条件来决定是否创建某个特定的bean 意义: Springboot实现自动配置的关键基础能力 2.常见conditional注解 @ConditionalOnBean 框架中存在某个Bean时生效 @ConditionalOnMissingBean 在Bean不存在时生效 @ConditionalOnClass框架中存在某个Class时生效 @ConditionalOnMissingClass在Class不

  • Spring boot中@Conditional和spring boot的自动配置实例详解

    我们知道,spring boot自动配置功能可以根据不同情况来决定spring配置应该用哪个,不应该用哪个,举个例子: Spring的JdbcTemplate是不是在Classpath里面?如果是,并且DataSource也存在,就自动配置一个JdbcTemplate的Bean Thymeleaf是不是在Classpath里面?如果是,则自动配置Thymeleaf的模板解析器.视图解析器.模板引擎 那个这个是怎么实现的呢?原因就在于它利用了Spring的条件化配置,条件化配置允许配置存在于应用中

  • Spring Boot中@ConditionalOnProperty的使用方法

    前言 在Spring Boot的自动配置中经常看到@ConditionalOnProperty注解的使用,本篇文章带大家来了解一下该注解的功能.下面话不多说了,来一起看看详细的介绍吧. Spring Boot中的使用 在Spring Boot的源码中,比如涉及到Http编码的自动配置.数据源类型的自动配置等大量的使用到了@ConditionalOnProperty的注解. HttpEncodingAutoConfiguration类中部分源代码: @Configuration(proxyBean

  • 浅谈SpringBoot中的@Conditional注解的使用

    概述 Spring boot 中的 @Conditional 注解是一个不太常用到的注解,但确实非常的有用,我们知道 Spring Boot 是根据配置文件中的内容,决定是否创建 bean,以及如何创建 bean 到 Spring 容器中,而 Spring boot 自动化配置的核心控制,就是 @Conditional 注解. @Conditional 注解是 Spring 4.0 之后出的一个注解,与其搭配的一个接口是 Condition,@Conditional 注解会根据具体的条件决定是否

  • Spring Boot @Conditional注解用法示例介绍

    引用Spring官方文档的说法介绍一下@Conditional注解:Spring5.0.15版本@Conditional注解官方文档 @Conditional表示仅当所有指定条件都匹配时,组件才有资格注册 . 该@Conditional注释可以在以下任一方式使用: 作为任何@Bean方法的方法级注释 作为任何类的直接或间接注释的类型级别注释 @Component,包括@Configuration类 作为元注释,目的是组成自定义构造型注释 改注解主要源码之一,通过match匹配,符合条件才装载到S

  • 基于SpringBoot核心原理(自动配置、事件驱动、Condition)

    前言 SpringBoot是Spring的包装,通过自动配置使得SpringBoot可以做到开箱即用,上手成本非常低,但是学习其实现原理的成本大大增加,需要先了解熟悉Spring原理.如果还不清楚Spring原理的,可以先查看博主之前的文章,本篇主要分析SpringBoot的启动.自动配置.Condition.事件驱动原理. 正文 启动原理 SpringBoot启动非常简单,因其内置了Tomcat,所以只需要通过下面几种方式启动即可: @SpringBootApplication(scanBas

  • 如何使用SpringBootCondition更自由地定义条件化配置

    Conditional如何使用 @Conditional 是 SpringFramework 的功能, SpringBoot 在它的基础上定义了 @ConditionalOnClass , @ConditionalOnProperty 的一系列的注解来实现更丰富的内容. 定义一个自定义标签 import com.example.conditional.MyConditional; import org.springframework.context.annotation.Conditional;

  • JS中比Switch...Case更优雅的多条件判断写法

    前言 前几天,本人负责编写网站上线的环境判断功能,其中涉及到大量多条件判断的code.对于多条件判断写法,大部分程序员都是采用if...else if...else或者switch...case的写法,但是有一种多条件判断写法,比传统写法更加有趣且优雅--对象属性判断法. 实例展示 废话不多说了,下面直接用三个实例,给大家分别展示三种不同的多条件判断写法. 1. if...else if...else function whatFood(mealtime) { let food = ''; if

  • 分享5个小技巧让你写出更好的 JavaScript 条件语句

    在使用 JavaScript 时,我们常常要写不少的条件语句.这里有五个小技巧,可以让你写出更干净.漂亮的条件语句. 1. 使用 Array.includes 来处理多重条件 举个栗子 : // 条件语句 function test(fruit) { if (fruit == 'apple' || fruit == 'strawberry') { console.log('red'); } } 乍一看,这么写似乎没什么大问题.然而,如果我们想要匹配更多的红色水果呢,比方说『樱桃』和『蔓越莓』?我

  • Spring基于@Conditional条件化装配bean

    一 前言 理解spring的如何根据条件装配bean有助于我们更好使用springboot进行开发,和源码理解: 二 @Conditional 装配bean 思路如下 Spring中提供了@Conditional注解实现条件化是否装配bean,这样可以根据条件动态的装配bean: 要判定@Conditional 注解是否该装配bean还需要Condition 接口配合,我们只须实现 Condition 接口,重写matches 方法: 根据matches方法返回的布尔值进行判定@Conditio

  • solr 配置中文分析器/定义业务域/配置DataImport功能方法(测试用)

    一.配置中文分析器 使用IKAnalyzer 配置方法: 1)把IK的jar包添加到solr工程中/WEB-INF/lib目录下 2)把IK的配置文件扩展词典,放到classpath下./WEB-INF/classes目录下 3)在schema.xml中定义FieldType,指定使用IK作为分析器 <!-- IKAnalyzer--> <fieldType name="text_ik" class="solr.TextField"> <

  • Spring Boot 深入分析AutoConfigurationImportFilter自动化条件配置源码

    目录 1. AutoConfigurationImportFilter的作用 2. AutoConfigurationImportFilter UML类图说明 3. FilteringSpringBootCondition抽象类 4. AutoConfigurationImportSelector类 5. 总结 1. AutoConfigurationImportFilter的作用 之前讲解了SpringBoot的Conditional的自动化条件配置,我们分析了内部是如何具体实现,在整个实现当

  • 浅析SpringBoot自动化配置原理实现

    绪论 什么是SpringBoot? Spring Boot 是所有基于 Spring 开发的项目的起点.Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件.简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架(不知道这样比喻是否合适). SpringBoot四个主要特性 SpringBoot Starter:他将常用的依赖分组进行了整

  • Spring Boot 详细分析Conditional自动化配置注解

    目录 1. Spring Boot Condition功能与作用 2. Conditional条件化系列注解介绍 3. Conditional条件化注解的实现原理 4. Conditional核心之matches匹配接口 5. Conditional核心之条件化注解具体实现 6. 总结 1. Spring Boot Condition功能与作用 @Conditional是基于条件的自动化配置注解, 由Spring 4框架推出的新特性. 在一个服务工程, 通常会存在多个配置环境, 比如常见的DEV

  • 详解Spring注解 @Configuration

    目录 @Configuration 注解的概述 底层原理 与 Spring IoC 容器的集成 Bean 的定义和装配的实现 条件化配置的实现 配置类的加载和实例化过程 总结 Spring 提供了丰富的特性和功能,包括依赖注入.面向切面编程.事务管理.数据访问.Web应用程序开发等.其中,@Configuration 是 Spring 中的一个注解,它用于标记一个类为配置类,通过配置类可以定义和组装 Spring Bean,并且支持高度灵活的配置方式.在本文中,我们将深入探讨 @Configur

  • Spring Boot实战教程之自动配置详解

    前言 大家应该都有所了解,随着Ruby.Groovy等动态语言的流行,相比较之下Java的开发显得格外笨重.繁多的配置.低下的开发效率.复杂的部署流程以及第三方技术集成难度大等问题一直被人们所诟病.随着Spring家族中的新星Spring Boot的诞生,这些问题都在逐渐被解决. 个人觉得Spring Boot中最重要的两个优势就是可以使用starter简化依赖配置和Spring的自动配置.下面这篇文章将给大家详细介绍Spring Boot自动配置的相关内容,话不多说,来一起看看详细的介绍. 使

随机推荐