Micronaut Scopes
Micronaut 具有基于 JSR-330 的可扩展 bean 作用域机制。支持以下默认范围:
内置范围
类型 | 描述 |
---|---|
Singleton 作用域表示将只存在一个 bean 实例 |
|
Context scope表示bean会和ApplicationContext同时创建(eager initialization) |
|
Prototype作用域表示每次注入时都会创建一个新的bean实例 |
|
Infrastructure 作用域表示不能使用 @Replaces 覆盖或替换的 bean,因为它对系统的功能至关重要。 |
|
@ThreadLocal 范围是一个自定义范围,它通过 ThreadLocal 为每个线程关联一个 bean |
|
@Refreshable 范围是一个自定义范围,它允许通过 /refresh 端点刷新 bean 的状态。 |
|
@RequestScope 作用域是一个自定义作用域,表示创建了一个新的 bean 实例并与每个 HTTP 请求相关联 |
@Prototype 注解是@Bean 的同义词,因为默认作用域是原型。
可以通过定义实现 CustomScope 接口的 @Singleton bean 来添加其他范围。
请注意,当启动 ApplicationContext 时,默认情况下 @Singleton-scoped beans 是延迟和按需创建的。这是为了优化启动时间而设计的。
如果这对您的用例造成问题,您可以选择使用 @Context 注释,它将对象的生命周期绑定到 ApplicationContext 的生命周期。换句话说,当 ApplicationContext 启动时,您的 bean 将被创建。
或者,使用 @Parallel 注释任何 @Singleton-scoped bean,这允许在不影响整体启动时间的情况下并行初始化 bean。
如果您的 bean 未能并行初始化,应用程序将自动关闭。
单例的急切初始化
在某些情况下,@Singleton bean 的急切初始化可能是可取的,例如在 AWS Lambda 上,分配给 Lambda 构建的 CPU 资源多于执行。
您可以指定是否使用 ApplicationContextBuilder 接口预先初始化 @Singleton-scoped bean:
启用单例的急切初始化
public class Application {
public static void main(String[] args) {
Micronaut.build(args)
.eagerInitSingletons(true) (1)
.mainClass(Application.class)
.start();
}
}
将 eager init 设置为 true 会初始化所有单例
当您在无服务器函数等环境中使用 Micronaut 时,您将没有应用程序类,而是扩展了 Micronaut 提供的类。在这些情况下,Micronaut 提供了一些方法,您可以重写这些方法来增强 ApplicationContextBuilder
覆盖 newApplicationContextBuilder()
public class MyFunctionHandler extends MicronautRequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
...
@Nonnull
@Override
protected ApplicationContextBuilder newApplicationContextBuilder() {
ApplicationContextBuilder builder = super.newApplicationContextBuilder();
builder.eagerInitSingletons(true);
return builder;
}
...
}
@ConfigurationReader beans,例如@EachProperty 或@ConfigurationProperties 是单例bean。要急切地初始化配置但保持其他 @Singleton-scoped bean 创建惰性,请使用 eagerInitConfiguration:
启用配置的急切初始化
public class Application {
public static void main(String[] args) {
Micronaut.build(args)
.eagerInitConfiguration(true) (1)
.mainClass(Application.class)
.start();
}
}
将 eager init 设置为 true 会初始化所有配置读取器 bean。
可刷新 Scope
Refreshable 范围是一个自定义范围,允许通过以下方式刷新 bean 的状态:
- /refresh endpoint.
RefreshEvent 的发布。
以下示例说明了 @Refreshable 范围行为。
Java | Groovy | Kotlin |
|
|
|
WeatherService 使用 @Refreshable 范围进行注释,该范围存储一个实例,直到触发刷新事件
forecast 属性的值在创建 bean 时设置为固定值,并且在刷新 bean 之前不会更改
如果调用 latestForecast() 两次,您将看到相同的响应,例如“Scattered Clouds 01/Feb/18 10:29.199”。
当调用 /refresh 端点或发布 RefreshEvent 时,该实例将失效,并在下次请求该对象时创建一个新实例。例如:
Java | Groovy | Kotlin |
|
|
|
元注释的范围
可以在元注释上定义范围,然后您可以将其应用于您的类。考虑以下示例元注释:
Driver.java Annotation
Java | Groovy | Kotlin |
|
|
|
该范围使用 Requires 声明对 Car 类的要求
注解声明为@Singleton
在上面的示例中,@Singleton 注释应用于 @Driver 注释,这导致每个用 @Driver 注释的类都被视为单例。
请注意,在这种情况下,无法在应用注释时更改范围。例如,以下不会覆盖@Driver 声明的范围并且是无效的:
Declaring Another Scope
@Driver
@Prototype
class Foo {}
对于可覆盖的范围,请改为使用 @Driver 上的 DefaultScope 批注,它允许在不存在其他范围的情况下指定默认范围:
Using @DefaultScope
Java | Groovy | Kotlin |
|
|
|
如果未指定,则 DefaultScope 声明要使用的范围
更多建议: