有時您可能需要將建議應用于 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 注釋以指示應該攔截構造函數(shù)
@InterceptorBinding 定義用于指示應該發(fā)生@PostConstruct 攔截
@InterceptorBinding 定義用于指示應該發(fā)生@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 需要一個參數(shù)來完成構造
任何@PreDestroy 或@PostConstruct 方法在攔截器鏈中最后執(zhí)行
現(xiàn)在您可以為構造函數(shù)攔截定義 ConstructorInterceptor bean,為 @PostConstruct 或 @PreDestroy 攔截定義 MethodInterceptor bean。
以下工廠定義了一個 ConstructorInterceptor,它攔截 Product 實例的構造并將它們注冊到一個假設的 ProductService 中,首先驗證產(chǎn)品名稱:
定義構造函數(shù)攔截器
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
可以根據(jù)需要檢索和修改構造函數(shù)參數(shù)值
可以使用 proceed() 方法調用構造函數(shù)
定義攔截 @PostConstruct 和 @PreDestroy 方法的 MethodInterceptor 實例與為常規(guī)方法定義攔截器沒有什么不同。但是請注意,您可以使用傳遞的 MethodInvocationContext 來識別正在發(fā)生的攔截類型,并相應地調整代碼,如以下示例所示:
定義構造函數(shù)攔截器
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攔截處理
更多建議: