有时您可能需要将建议应用于 bean 的生命周期。有 3 种类型的建议适用于这种情况:
Micronaut 通过允许定义额外的 @InterceptorBinding 元注解来支持这 3 个用例。
考虑以下注解定义:
AroundConstruct 示例
Java |
Groovy |
Kotlin |
import io.micronaut.aop.*;
import io.micronaut.context.annotation.Prototype;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@AroundConstruct // (1)
@InterceptorBinding(kind = InterceptorKind.POST_CONSTRUCT) // (2)
@InterceptorBinding(kind = InterceptorKind.PRE_DESTROY) // (3)
@Prototype // (4)
public @interface ProductBean {
}
|
import io.micronaut.aop.*
import io.micronaut.context.annotation.Prototype
import java.lang.annotation.*
@Retention(RetentionPolicy.RUNTIME)
@AroundConstruct // (1)
@InterceptorBinding(kind = InterceptorKind.POST_CONSTRUCT) // (2)
@InterceptorBinding(kind = InterceptorKind.PRE_DESTROY) // (3)
@Prototype // (4)
@interface ProductBean {
}
|
import io.micronaut.aop.AroundConstruct
import io.micronaut.aop.InterceptorBinding
import io.micronaut.aop.InterceptorBindingDefinitions
import io.micronaut.aop.InterceptorKind
import io.micronaut.context.annotation.Prototype
@Retention(AnnotationRetention.RUNTIME)
@AroundConstruct // (1)
@InterceptorBindingDefinitions(
InterceptorBinding(kind = InterceptorKind.POST_CONSTRUCT), // (2)
InterceptorBinding(kind = InterceptorKind.PRE_DESTROY) // (3)
)
@Prototype // (4)
annotation class ProductBean
|
添加@AroundConstruct 注释以指示应该拦截构造函数
@InterceptorBinding 定义用于指示应该发生@PostConstruct 拦截
@InterceptorBinding 定义用于指示应该发生@PreDestroy 拦截
该 bean 被定义为 @Prototype,因此每个注入点都需要一个新实例
请注意,如果您不需要 @PostConstruct 和 @PreDestroy 拦截,您可以简单地删除这些绑定。
然后可以在目标类上使用 @ProductBean 注释:
使用 AroundConstruct 元注释
Java |
Groovy |
Kotlin |
import io.micronaut.context.annotation.Parameter;
import jakarta.annotation.PreDestroy;
@ProductBean // (1)
public class Product {
private final String productName;
private boolean active = false;
public Product(@Parameter String productName) { // (2)
this.productName = productName;
}
public String getProductName() {
return productName;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
@PreDestroy // (3)
void disable() {
active = false;
}
}
|
import io.micronaut.context.annotation.Parameter
import jakarta.annotation.PreDestroy
@ProductBean // (1)
class Product {
final String productName
boolean active = false
Product(@Parameter String productName) { // (2)
this.productName = productName
}
@PreDestroy // (3)
void disable() {
active = false
}
}
|
import io.micronaut.context.annotation.Parameter
import jakarta.annotation.PreDestroy
@ProductBean // (1)
class Product(@param:Parameter val productName: String ) { // (2)
var active: Boolean = false
@PreDestroy
fun disable() { // (3)
active = false
}
}
|
@ProductBean 注释定义在 Product 类型的类上
@Parameter 注解表明这个 bean 需要一个参数来完成构造
任何@PreDestroy 或@PostConstruct 方法在拦截器链中最后执行
现在您可以为构造函数拦截定义 ConstructorInterceptor bean,为 @PostConstruct 或 @PreDestroy 拦截定义 MethodInterceptor bean。
以下工厂定义了一个 ConstructorInterceptor,它拦截 Product 实例的构造并将它们注册到一个假设的 ProductService 中,首先验证产品名称:
定义构造函数拦截器
Java |
Groovy |
Kotlin |
import io.micronaut.aop.*;
import io.micronaut.context.annotation.Factory;
@Factory
public class ProductInterceptors {
private final ProductService productService;
public ProductInterceptors(ProductService productService) {
this.productService = productService;
}
}
@InterceptorBean(ProductBean.class)
ConstructorInterceptor<Product> aroundConstruct() { // (1)
return context -> {
final Object[] parameterValues = context.getParameterValues(); // (2)
final Object parameterValue = parameterValues[0];
if (parameterValue == null || parameterValues[0].toString().isEmpty()) {
throw new IllegalArgumentException("Invalid product name");
}
String productName = parameterValues[0].toString().toUpperCase();
parameterValues[0] = productName;
final Product product = context.proceed(); // (3)
productService.addProduct(product);
return product;
};
}
|
import io.micronaut.aop.*
import io.micronaut.context.annotation.Factory
@Factory
class ProductInterceptors {
private final ProductService productService
ProductInterceptors(ProductService productService) {
this.productService = productService
}
}
@InterceptorBean(ProductBean.class)
ConstructorInterceptor<Product> aroundConstruct() { // (1)
return { context ->
final Object[] parameterValues = context.parameterValues // (2)
final Object parameterValue = parameterValues[0]
if (parameterValue == null || parameterValues[0].toString().isEmpty()) {
throw new IllegalArgumentException("Invalid product name")
}
String productName = parameterValues[0].toString().toUpperCase()
parameterValues[0] = productName
final Product product = context.proceed() // (3)
productService.addProduct(product)
return product
}
}
|
import io.micronaut.aop.*
import io.micronaut.context.annotation.Factory
@Factory
class ProductInterceptors(private val productService: ProductService) {
}
@InterceptorBean(ProductBean::class)
fun aroundConstruct(): ConstructorInterceptor<Product> { // (1)
return ConstructorInterceptor { context: ConstructorInvocationContext<Product> ->
val parameterValues = context.parameterValues // (2)
val parameterValue = parameterValues[0]
require(!(parameterValue == null || parameterValues[0].toString().isEmpty())) { "Invalid product name" }
val productName = parameterValues[0].toString().uppercase()
parameterValues[0] = productName
val product = context.proceed() // (3)
productService.addProduct(product)
product
}
}
|
定义了一个新的 @InterceptorBean,它是一个 ConstructorInterceptor
可以根据需要检索和修改构造函数参数值
可以使用 proceed() 方法调用构造函数
定义拦截 @PostConstruct 和 @PreDestroy 方法的 MethodInterceptor 实例与为常规方法定义拦截器没有什么不同。但是请注意,您可以使用传递的 MethodInvocationContext 来识别正在发生的拦截类型,并相应地调整代码,如以下示例所示:
定义构造函数拦截器
Java |
Groovy |
Kotlin |
@InterceptorBean(ProductBean.class) // (1)
MethodInterceptor<Product, Object> aroundInvoke() {
return context -> {
final Product product = context.getTarget();
switch (context.getKind()) {
case POST_CONSTRUCT: // (2)
product.setActive(true);
return context.proceed();
case PRE_DESTROY: // (3)
productService.removeProduct(product);
return context.proceed();
default:
return context.proceed();
}
};
}
|
@InterceptorBean(ProductBean.class) // (1)
MethodInterceptor<Product, Object> aroundInvoke() {
return { context ->
final Product product = context.getTarget()
switch (context.kind) {
case InterceptorKind.POST_CONSTRUCT: // (2)
product.setActive(true)
return context.proceed()
case InterceptorKind.PRE_DESTROY: // (3)
productService.removeProduct(product)
return context.proceed()
default:
return context.proceed()
}
}
}
|
@InterceptorBean(ProductBean::class)
fun aroundInvoke(): MethodInterceptor<Product, Any> { // (1)
return MethodInterceptor { context: MethodInvocationContext<Product, Any> ->
val product = context.target
return@MethodInterceptor when (context.kind) {
InterceptorKind.POST_CONSTRUCT -> { // (2)
product.active = true
context.proceed()
}
InterceptorKind.PRE_DESTROY -> { // (3)
productService.removeProduct(product)
context.proceed()
}
else -> context.proceed()
}
}
}
|
定义了一个新的 @InterceptorBean,它是一个 MethodInterceptor
@PostConstruct拦截处理
@PreDestroy拦截处理
更多建议: