Micronaut 配置注入

2023-03-01 14:40 更新

您可以使用 @Value 注释将配置值注入到 bean 中。

使用@Value 注解

考虑以下示例:

@Value Example

 Java Groovy  Kotlin 
import io.micronaut.context.annotation.Value;

import jakarta.inject.Singleton;

@Singleton
public class EngineImpl implements Engine {

    @Value("${my.engine.cylinders:6}") // (1)
    protected int cylinders;

    @Override
    public int getCylinders() {
        return cylinders;
    }

    @Override
    public String start() {// (2)
        return "Starting V" + getCylinders() + " Engine";
    }

}
import io.micronaut.context.annotation.Value

import jakarta.inject.Singleton

@Singleton
class EngineImpl implements Engine {

    @Value('${my.engine.cylinders:6}') // (1)
    protected int cylinders

    @Override
    int getCylinders() {
        cylinders
    }

    @Override
    String start() { // (2)
        "Starting V$cylinders Engine"
    }
}
import io.micronaut.context.annotation.Value

import jakarta.inject.Singleton

@Singleton
class EngineImpl : Engine {

    @Value("\${my.engine.cylinders:6}") // (1)
    override var cylinders: Int = 0
        protected set

    override fun start(): String { // (2)
        return "Starting V$cylinders Engine"
    }
}
  1. @Value 注解接受一个可以嵌入占位符值的字符串(默认值可以通过在冒号 : 字符后指定一个值来提供)。还要尽量避免将成员可见性设置为私有,因为这需要 Micronaut 框架使用反射。更喜欢使用受保护的。

  2. 然后可以在代码中使用注入的值。

请注意,@Value 也可用于注入静态值。例如,以下注入数字 10:

Static @Value Example

@Value("10")
int number;

当用于组合静态内容和占位符的注入值时,这会更有用。例如设置一个 URL:

Placeholders with @Value

@Value("http://${my.host}:${my.port}")
URL url;

在上面的示例中,URL 由配置中必须存在的两个占位符属性构成:my.host 和 my.port。

请记住,要在占位符表达式中指定默认值,请使用冒号 : 字符。但是,如果您指定的默认值包含冒号,则必须使用反引号对值进行转义。例如:

Placeholders with @Value

@Value("${my.url:`http://foo.com`}")
URL url;

请注意,@Value 本身在属性值占位符的解析方面没有什么特别之处。

由于 Micronaut 对注释元数据的广泛支持,您可以在任何注释上使用属性占位符表达式。例如,要使 @Controller 的路径可配置,您可以执行以下操作:

@Controller("${hello.controller.path:/hello}")
class HelloController {
    ...
}

在上面的例子中,如果在配置中指定了 hello.controller.path,控制器将被映射到指定的路径,否则它将被映射到 /hello。

您还可以使 @Client 的目标服务器可配置(尽管服务发现方法通常更好),例如:

@Client("${my.server.url:`http://localhost:8080`}")
interface HelloClient {
    ...
}

在上面的示例中,属性 my.server.url 可用于配置客户端,否则客户端会回退到本地主机地址。

使用@Property 注解

回想一下,@Value 注释接收一个 String 值,它可以是静态内容和占位符表达式的混合。如果您尝试执行以下操作,这可能会导致混淆:

Incorrect usage of @Value

@Value("my.url")
String url;

在上述情况下,文字字符串值 my.url 被注入并设置为 url 字段,而不是应用程序配置中 my.url 属性的值。这是因为@Value 仅解析指定给它的值内的占位符。

要注入特定的属性名称,您最好使用 @Property:

Using @Property

 Java Groovy  Kotlin 
import io.micronaut.context.annotation.Property;

import jakarta.inject.Inject;
import jakarta.inject.Singleton;

@Singleton
public class Engine {

    @Property(name = "my.engine.cylinders") // (1)
    protected int cylinders; // (2)

    private String manufacturer;

    public int getCylinders() {
        return cylinders;
    }

    public String getManufacturer() {
        return manufacturer;
    }

    @Inject
    public void setManufacturer(@Property(name = "my.engine.manufacturer") String manufacturer) { // (3)
        this.manufacturer = manufacturer;
    }

}
import io.micronaut.context.annotation.Property

import jakarta.inject.Singleton

@Singleton
class Engine {

    @Property(name = "my.engine.cylinders") // (1)
    protected int cylinders // (2)

    @Property(name = "my.engine.manufacturer") //(3)
    String manufacturer

    int getCylinders() {
        cylinders
    }
}
import io.micronaut.context.annotation.Property

import jakarta.inject.Inject
import jakarta.inject.Singleton


@Singleton
class Engine {

    @field:Property(name = "my.engine.cylinders") // (1)
    protected var cylinders: Int = 0 // (2)

    @set:Inject
    @setparam:Property(name = "my.engine.manufacturer") // (3)
    var manufacturer: String? = null

    fun cylinders(): Int {
        return cylinders
    }
}
  1. my.engine.cylinders 属性从配置中解析并注入到字段中。

  2. 受注入的字段不应该是私有的,因为必须使用昂贵的反射

  3. @Property注解用于通过setter注入

因为无法使用@Property 定义默认值,如果该值不存在或无法转换为所需的类型,bean 实例化将失败。

以上改为注入从应用程序配置解析的 my.url 属性的值。如果在配置中找不到该属性,则会抛出异常。与其他类型的注入一样,注入点也可以用@Nullable注解,使注入成为可选的。

您还可以使用此功能来解析子映射。例如,考虑以下配置:

 Properties Yaml  Toml  Groovy  Hocon  JSON 
datasources.default.name=mydb
jpa.default.properties.hibernate.hbm2ddl.auto=update
jpa.default.properties.hibernate.show_sql=true
datasources:
  default:
    name: 'mydb'
jpa:
  default:
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        show_sql: true
[datasources]
  [datasources.default]
    name="mydb"
[jpa]
  [jpa.default]
    [jpa.default.properties]
      [jpa.default.properties.hibernate]
        [jpa.default.properties.hibernate.hbm2ddl]
          auto="update"
        show_sql=true
datasources {
  'default' {
    name = "mydb"
  }
}
jpa {
  'default' {
    properties {
      hibernate {
        hbm2ddl {
          auto = "update"
        }
        show_sql = true
      }
    }
  }
}
{
  datasources {
    default {
      name = "mydb"
    }
  }
  jpa {
    default {
      properties {
        hibernate {
          hbm2ddl {
            auto = "update"
          }
          show_sql = true
        }
      }
    }
  }
}
{
  "datasources": {
    "default": {
      "name": "mydb"
    }
  },
  "jpa": {
    "default": {
      "properties": {
        "hibernate": {
          "hbm2ddl": {
            "auto": "update"
          },
          "show_sql": true
        }
      }
    }
  }
}

要解析仅包含以 hibernate 开头的属性的扁平化映射,请使用 @Property,例如:

Using @Property

@Property(name = "jpa.default.properties")
Map<String, String> jpaProperties;

注入的映射将包含键 hibernate.hbm2ddl.auto 和 hibernate.show_sql 及其值。

@MapFormat 注释可用于根据您想要嵌套键还是平面键来自定义注入的映射,并且它允许通过 StringConvention 枚举自定义键样式。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号