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 注解接受一個可以嵌入占位符值的字符串(默認(rèn)值可以通過在冒號 : 字符后指定一個值來提供)。還要盡量避免將成員可見性設(shè)置為私有,因為這需要 Micronaut 框架使用反射。更喜歡使用受保護的。

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

請注意,@Value 也可用于注入靜態(tài)值。例如,以下注入數(shù)字 10:

Static @Value Example

@Value("10")
int number;

當(dāng)用于組合靜態(tài)內(nèi)容和占位符的注入值時,這會更有用。例如設(shè)置一個 URL:

Placeholders with @Value

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

在上面的示例中,URL 由配置中必須存在的兩個占位符屬性構(gòu)成:my.host 和 my.port。

請記住,要在占位符表達式中指定默認(rèn)值,請使用冒號 : 字符。但是,如果您指定的默認(rèn)值包含冒號,則必須使用反引號對值進行轉(zhuǎn)義。例如:

Placeholders with @Value

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

請注意,@Value 本身在屬性值占位符的解析方面沒有什么特別之處。

由于 Micronaut 對注釋元數(shù)據(jù)的廣泛支持,您可以在任何注釋上使用屬性占位符表達式。例如,要使 @Controller 的路徑可配置,您可以執(zhí)行以下操作:

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

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

您還可以使 @Client 的目標(biāo)服務(wù)器可配置(盡管服務(wù)發(fā)現(xiàn)方法通常更好),例如:

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

在上面的示例中,屬性 my.server.url 可用于配置客戶端,否則客戶端會回退到本地主機地址。

使用@Property 注解

回想一下,@Value 注釋接收一個 String 值,它可以是靜態(tài)內(nèi)容和占位符表達式的混合。如果您嘗試執(zhí)行以下操作,這可能會導(dǎo)致混淆:

Incorrect usage of @Value

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

在上述情況下,文字字符串值 my.url 被注入并設(shè)置為 url 字段,而不是應(yīng)用程序配置中 my.url 屬性的值。這是因為@Value 僅解析指定給它的值內(nèi)的占位符。

要注入特定的屬性名稱,您最好使用 @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. 受注入的字段不應(yīng)該是私有的,因為必須使用昂貴的反射

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

因為無法使用@Property 定義默認(rèn)值,如果該值不存在或無法轉(zhuǎn)換為所需的類型,bean 實例化將失敗。

以上改為注入從應(yīng)用程序配置解析的 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 注釋可用于根據(jù)您想要嵌套鍵還是平面鍵來自定義注入的映射,并且它允許通過 StringConvention 枚舉自定義鍵樣式。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號