干掉祖传代码 之 spring的@Value注解

from:https://tuhrig.de/why-using-springs-value-annotation-is-bad/

为什么使用Spring的@Value注释不好

@Value

配置是每个拥有数百行代码的每个应用程序的重要主题。如果您使用的是Spring,通常会使用Spring的@Value注释从Java属性文件中加载值。可能看起来像这样:

如果这样做,Spring将从my.config.property.key 属性文件中将键的值注入到您的类中,您就完成了。简单!也许太容易了……

会发生什么…

当您在应用程序中使用此技术时会发生什么?好吧,只要需要一些属性,就可以注入它。您将其注入服务,控制器和组件中,并将正确的属性注入不同的类中。这很简单,而且绝对是该机制的目的。

但是,这仅意味着分散整个应用程序的配置。每个类都可以选择几个要使用的属性。您将不知道或无法控制哪个类正在使用哪些属性。最后,您将对项目进行全文搜索,以查找使用单个键的位置。如果您想重命名这些键之一,或者需要为单元测试中的每个类的每个属性设置每个属性,您将获得很多乐趣。

配置即服务

取而代之的是,配置也应该是应用程序的封装服务,例如任何其他功能。您将持久性封装在DAO中,将REST服务封装在控制器中,并将安全性封装在身份验证器中。那么为什么不封装配置呢?

如果这样做,您将负有单一责任,可以加载并从中获取配置。与任何其他服务一样,您可以轻松更改实现。也许您不想从属性文件中加载属性,而是从数据库或Web服务中加载!如果将配置封装在服务中,那没什么大不了的。您只需更改实现。您还可以为您的配置编写一些单元测试(为什么不这样做?当组合属性或根据其他几个属性确定某个配置时,配置会变得很复杂!),也可以对配置服务中的属性进行完整性检查。您可以进行日志记录,可以进行安全保护(也许密码文件的路径在所有地方都不应该看到,对不对?),可以进行缓存,可以进行……好吧,您就明白了。

甚至更好

如果您使用的是Spring Boot(不仅是Spring),则无需重新发明轮子。Spring Boot提供了一种优雅的方式来将配置与应用程序的其余部分分开:@ConfigurationProperties通过使用Spring Boot的@ConfigurationProperties,您可以轻松地将配置封装在一个单独的类中,并避免在整个代码中分散对配置文件的直接依赖关系。在这里阅读更多

from:https://tuhrig.de/using-configurationproperties-to-separate-service-and-configuration

使用@ConfigurationProperties分隔服务和配置

大约两年前,我写了一篇文章“为什么使用Spring的@Value注释不好”。我描述了为什么@Value在整个代码中都应避免使用注释。通过@Value在服务,控制器和其他Spring组件中使用批注,您将在整个应用程序中分散配置。在最坏的情况下,您将在多个类中连接相同的值。如果您想在某天更改此值,则需要触摸所有此类。

取而代之的是,配置应该像数据库访问或REST端点一样是应用程序的封装方面。我们希望将配置与实际服务,控制器和组件分开。

Spring Boot的方法

Spring Boot提供了一个名为的注释@ConfigurationProperties正如您在这里可以读到的,它是为分离和外部化配置而设计的。那就是我们想要的!

让我们举个例子,并假设我们要配置与外部REST服务(它也可以是数据库或其他任何东西)的连接。我们需要一个配置,包括用户名,密码和URL。配置文件(application.properties)如下所示:

通过使用Spring Boot的@ConfigurationProperties注释,我们首先将编写一个Java类来表示此配置:

如您所见,属性文件及其Java表示形式之间有着非常明显的匹配。让我们看看如何使用此类:

如您所见,我们将所有配置封装在一个类中,该类注入了我们的服务。该服务不再知道配置来自何处。它只知道它可以从MySuperServiceConfig类中接收配置分离完成!

我们还能做什么?

我们不仅分离了配置,而且将其转换为Java类!这意味着我们可以使用它进行编码!这里有一些例子和想法:

应用默认值

我们仅可以为应该配置但不太可能配置的属性应用默认值。假设我们有一个端口:

在大多数情况下,端口将是8080。仅在极少数情况下,我们才会在测试系统中使用另一个端口。在这种情况下,我们可以应用默认值:

工艺配置

让我们假设以下配置:

由于某些原因,我们希望能够自行配置每个属性。但是,在服务中,我们需要一个URL :http://some.where.com:8080/api/v1我们可以在我们的配置类中做到这一点!

创建不同的实现

我们的配置刚刚成为Spring Bean。这也意味着,我们可以用它来完成所有常见的Spring事情!例如,创建不同的实现。

通过这样做,我们最终得到了与“为什么使用Spring的@Value注释不好”中描述的解决方案类似的解决方案配置成为我们隐藏在界面后面的服务。我们可以更改获取配置的方式(从属性文件,硬编码或从云中的配置服务器)以及映射和处理方式。我们的实际服务将仅包含业务逻辑,而不必处理配置问题。

最好的问候,
托马斯

更多

from:https://www.baeldung.com/spring-value-defaults

将Spring @Value与默认值一起使用

1.概述

 

Spring的@Value注释提供了一种方便的方法来将属性值注入到组件中。在属性可能不存在的情况下提供合理的默认值也很有用

这就是我们在本文中要重点关注的内容–如何为@Value Spring批注指定默认值有关@Value的更详细的快速指南,请参见此处的文章

2.字符串默认值

 

让我们看一下为String属性设置默认值的基本语法

  @Value("${some.key:my default value}")
  private String stringWithDefaultValue;

如果some.key无法解析,则将stringW ithDefaultValue设置为默认值“ my default value”

同样,我们可以将零长度的String设置为默认值:

  @Value("${some.key:})"
  private String stringWithBlankDefaultValue;

3.基元

 

要为基本类型(例如booleanint)设置默认值,我们使用文字值:

  @Value("${some.key:true}")
  private boolean booleanWithDefaultValue;
  @Value("${some.key:42}")
  private int intWithDefaultValue;

如果愿意,我们可以使用原始包装器,方法是将类型更改为BooleanInteger

4.数组

 

我们还可以将逗号分隔的值列表注入数组:

  @Value("${some.key:one,two,three}")
  private String[] stringArrayWithDefaults;
   
  @Value("${some.key:1,2,3}")
  private int[] intArrayWithDefaults;

在上面的第一个示例中,值“一个”,“两个”和“三个”作为默认值注入到stringArrayWithDefaults中

在第二个示例中,值1、2和3作为默认值注入到intArrayWithDefaults中

5.使用SpEL

 

我们还可以使用Spring Expression Language(SpEL)指定表达式和默认值。

在下面的示例中,我们希望将some.system.key设置为系统属性,如果未设置,则希望使用“我的默认系统属性值”作为默认值:

  @Value("#{systemProperties['some.key'] ?: 'my default system property value'}")
  private String spelWithDefaultValue;

六,结论

 

在这篇快速的文章中,我们研究了如何为希望使用Spring的@Value注释注入的属性设置默认值

像往常一样,本文中使用的所有代码示例都可以在GitHub project中找到

from:https://stackoverflow.com/questions/11991194/can-i-set-null-as-the-default-value-for-a-value-in-spring

Can I set null as the default value for a @Value in Spring? 

You must set the nullValue of the PropertyPlaceholderConfigurer. For the example I'm using the string @null but you can also use the empty string as nullValue.

Now you can use the string @null to represent the null value

@Value("${stuff.value:@null}")
private String value;

from:https://farenda.com/spring/spring-value-default-value/

Spring @Value default value

This tutorial presents how to set default values in Spring @Value annotation, using properties syntax and Spring Expression Language (SPEL).

Spring Config class with static PropertySourcesPlaceholderConfigurer bean that is needed to resolve properties syntax inside @Value:

@Configuration
public class Config {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        // Needed by Spring to resolve ${} inside @Value:
        return new PropertySourcesPlaceholderConfigurer();
    }
}

Now a bean with defaults that we can access inside @Value:

@Component("defaults")
public class Defaults {
    public String getHostname() {
        return "default.host";
    }
}

Examples of setting default values using @Value:

@Component
public class SampleSpringComponent {
 
    @Value("${hostname : localhost}")
    private String hostName;
 
    @Value("${target.dir : #{systemProperties['java.io.tmpdir']}}")
    private String dir;
 
    @Value("${hostconfig.hostname : #{@defaults.hostname}}")
    private String spelHostname;
 
    @Value("#{systemProperties['java.user.home'] ?: '/tmp/default'}")
    private String spelDir;
}

Results:

Host name:  localhost
Directory:  /tmp
SPEL Host name:  default.host
SPEL Directory: /tmp/default

Summary of setting defaults:

  1. Property syntax use: ${expected : default}
  2. SPEL use: #{expected[‘value’] ?: default} (Elvis operator)
  3. SPEL expressions can be mixed with property syntax to access beans in context or use other complex expressions.

 from:https://stackoverflow.com/questions/31711308/spring-value-escape-colon-in-default-value

Spring @Value转义冒号(:)为默认值

61
 

更新: 对于4.2或更高版本的Spring,不需要单引号。Spring将第一个冒号视为特殊字符,并将其余所有字符用作单个字符串值。

对于4.2或更高版本的春季,

@Value("${prop.url:http://myurl.com}")

对于以前的版本,我相信单引号可以解决问题:

@Value("${prop.url:'http://myurl.com'}")

又见神码!

toString 做缓存?!笑话。。

貌似找到优雅退出的鼻祖了。 




原文地址:https://www.cnblogs.com/Chary/p/14011361.html