SpringBoot重点详解–@Conditional注解

SpringBoot重点详解–@Conditional注解目录 Conditional 注解自定义 ConditionalS 扩展注解在上一章 SpringBoot 重点详解配置文件 中曾简单介绍过如何利用 Profile 注解来根据指定 profile 是否被激活动态地决定是否要创建某一个 Bean 在这一章 我们将介绍另一种根据条件来装配 Bean 的新方法 使用 Conditional 注解 根据是否满足

目录

@Conditional注解

自定义Conditional

SpringBoot 扩展注解


在上一章 《SpringBoot重点详解–配置文件》中曾简单介绍过如何利用 @Profile 注解来根据指定 profile 是否被激活动态地决定是否要创建某一个 Bean 。

在这一章,我们将介绍另一种根据条件来装配 Bean 的新方法:使用 @Conditional 注解,根据是否满足指定的条件来决定是否装配 Bean 。

@Conditional注解

Conditional 是由 SpringFramework 提供的一个注解,位于 org.springframework.context.annotation 包内,定义如下。

package org.springframework.context.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Conditional { Class<? extends Condition>[] value(); }

Conditional 注解类里只有一个 value 属性,需传入一个 Condition 类型的数组,我们先来看看这个 Condition 接口长什么样。

package org.springframework.context.annotation; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.core.type.AnnotatedTypeMetadata; public interface Condition { boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }

其中,matches() 方法传入的参数 ConditionContext 是专门为 Condition 而设计的一个接口类,可以从中获取到Spring容器的以下对象信息。

SpringBoot重点详解--@Conditional注解

当一个 Bean 被 Conditional 注解修饰时,Spring容器会对数组中所有 Condition 接口的 matches() 方法进行判断,只有当其中所有 Condition 接口的 matches()方法都为 ture 时,才会创建 Bean 。

自定义Conditional

接下来,我们将以一个国际化 I18n Bean 动态创建为例(根据配置中的 i18n.lang 属性值来动态地创建国际化 I18n Bean),对如何使用 Conditional 注解进行简单举例:

  • 当 i18n.lang=zh_CN 就创建中文 I18nChs Bean, 
  • 当 i18n.lang=en_US 就创建英文 I18nEng Bean。  

创建好的两个 Condition 实现类 I18nChsCondition 和 I18nEngCondition 代码如下。

public class I18nChsCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { String lang = context.getEnvironment().getProperty("i18n.lang"); ConditionOutcome outCome = new ConditionOutcome("zh_CN".equals(lang), "i18n.lang=" + lang); return outCome; } } 
public class I18nEngCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { String lang = context.getEnvironment().getProperty("i18n.lang"); ConditionOutcome outCome = new ConditionOutcome("en_US".equals(lang), "i18n.lang=" + lang); return outCome; } }

I18n 接口定义如下。

public interface I18n { // 获取 name 属性的值 String i18n(String name); }

I18n 接口的两个实现类 I18nChs 和 I18nEng 定义如下。

@Component @Conditional(I18nChsCondition.class) public class I18nChsImpl implements I18n { Map<String, String> map = new HashMap<String, String>() { private static final long serialVersionUID = 1L; { put("lang", "中文"); } }; @Override public String i18n(String name) { return map.get(name); } }
@Component @Conditional(I18nEngCondition.class) public class I18nEngImpl implements I18n { Map<String, String> map = new HashMap<String, String>() { private static final long serialVersionUID = 1L; { put("lang", "English"); } }; @Override public String i18n(String name) { return map.get(name); } }

在启动类中添加测试代码代码如下。

@SpringBootApplication public class App { public static void main( String[] args ) { ConfigurableApplicationContext context = SpringApplication.run(App.class, args); I18n i18n = context.getBean(I18n.class); System.out.println(i18n.getClass().getName()); System.out.println(i18n.i18n("lang")); context.close(); } }

配置 application.properties 内容如下:

# language : zh_CN/Chinese,en_US/America i18n.lang=zh_CN

运行程序,打印结果:

com.pengjunlee.condition.I18nChsImpl 中文

配置 application.properties 内容如下:

# language : zh_CN/Chinese,en_US/America i18n.lang=en_US

再次运行程序,打印结果:

com.pengjunlee.condition.I18nEngImpl English

为了书写和调用方便,我们还可以把上面的条件定义成注解,以 I18nChsCondition 为例,定义代码如下。

@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(I18nChsCondition.class) public @interface I18nChs { }

将 I18nChs 注解添加到 I18nChsImpl 上。

@Component @I18nEng public class I18nChsImpl implements I18n {//内容同上,此处省略}

SpringBoot 扩展注解

从上面的示例不难看出,如果要使用我们自定义条件类实现起来还是有点小麻烦的,不过比较庆幸的是, SpringBoot 在  Conditional 注解的基础上已经提前为我们定义好了一系列功能丰富的注解,我们可以直接使用。

SpringBoot重点详解--@Conditional注解

接下来我们使用  ConditionalOnProperty 注解来实现上面的国际化示例。

仅需修改 I18nChsImpl 和 I18nEngImpl 两个实现组件类,其他代码不变,程序执行结果与之前相同。

@Component @ConditionalOnProperty(name = "i18n.lang", havingValue = "zh_CN", matchIfMissing = true) public class I18nChsImpl implements I18n {//内容同上,此处省略}
@Component @ConditionalOnProperty(name = "i18n.lang", havingValue = "en_US", matchIfMissing = false) public class I18nEngImpl implements I18n {//内容同上,此处省略}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232381.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • BWAPP之旅_腾旅通app

    BWAPP之旅_腾旅通appBWAPP下载BWAPP玩法

    2022年9月24日
    7
  • QThread源码浅析[通俗易懂]

    QThread源码浅析[通俗易懂]Qt版本Qt5.6.0,下面以Windows平台为例简单研究下QThread源码实现。1.仅研究下QThread::start()函数,其他细节在次不涉及:src\qtbase\src\corelib\thread\qthread_win.cppvoidQThread::start(Prioritypriority){Q_D(QThread);QMutexLocker…

    2022年5月28日
    76
  • ip addr add配置ip_ifconfig配置ip

    ip addr add配置ip_ifconfig配置ip今天一个老外在邮件列表上问了一个问题,就是ipaddradd和ifconfig的区别,我给他进行了解答,可能因为英语不好吧,解答的很简单,因此我还是要在这里详细说明一下。其实它们之间没有什么区别,只是表述方式不同罢了。如果你非常理解网络协议的原理以及网络的分层架构那么我想你就不会有这个问题,实际上,每一个网卡设备都有一个mac地址,但是却可以有多个网络层地址,比如IP地址,然而这个事实无法

    2022年7月27日
    18
  • H2 数据库简介_polardb 数据库

    H2 数据库简介_polardb 数据库H2数据库H2是使用Java开发的内嵌式数据库,开源。支持内存、文件等多种模式。常用于开发和测试环境。特性读操作快,写操作不如SQLite支持全文检索(提供了内置全文检索和ApacheLuncene的全文检索)可以通过浏览器操作数据库运行模式EmbeddedMode内嵌模式ServerModel服务器模式混合模式下载目前最新版本是1.4.200,于2019/10/14发布。Windows安装版本:https://h2database.co

    2022年10月12日
    4
  • telnet远程登录AAA认证

    telnet远程登录AAA认证R1<Huawei>system-view//进入全局配置模式[Huawei]sysnameR1//改名[R1]undoinfo-centerenable//关闭信息告警提示[R1]interfaceg0/0/0//进入g/0/0接口[R1-GigabitEthernet0/0/0]ipaddress192.168.100…

    2022年6月7日
    39
  • jsonpath表达式_postman中raw

    jsonpath表达式_postman中rawform-data:就是multipart/form-data,将表单内要上传的数据,处理为一条消息,以标签为单元,一个个的隔开。既可以上传键值对,也可以上传文件。multipart/form-data与x-www-form-urlencoded区别就是,multipart/form-data还可以上传文件等二

    2022年9月30日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号