Quarkus中是否存在Spring @After Advice的等效实现?
Quarkus中实现类似Spring @After Advice的方案
核心方案:使用Interceptor结合@AroundInvoke
Quarkus没有直接对应Spring @After Advice的注解,但可以通过**拦截器(Interceptor)**的@AroundInvoke方法,配合try-finally块实现等效逻辑——不管目标方法执行成功还是抛出异常,最终都会执行指定逻辑来触发事件。
步骤1:定义自定义拦截器注解
先创建一个自定义注解,用来标记需要被拦截的方法:
import jakarta.interceptor.InterceptorBinding; import java.lang.annotation.*; @InterceptorBinding @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface AfterExecution { }
步骤2:实现拦截器逻辑
编写拦截器类,在@AroundInvoke方法里用try-finally包裹目标方法调用,finally块中执行事件触发逻辑:
import jakarta.interceptor.AroundInvoke; import jakarta.interceptor.Interceptor; import jakarta.interceptor.InvocationContext; @Interceptor @AfterExecution public class AfterExecutionInterceptor { @AroundInvoke public Object execute(InvocationContext ctx) throws Exception { Object result = null; Exception thrownException = null; try { // 执行目标方法 result = ctx.proceed(); return result; } catch (Exception e) { thrownException = e; throw e; } finally { // 这里写无论成功/失败都要执行的逻辑,比如触发事件 triggerEvent(ctx.getMethod().getName(), result, thrownException); } } private void triggerEvent(String methodName, Object result, Exception exception) { // 实现你的事件触发逻辑,比如发送CDI事件 // 示例:如果是CDI事件,可以注入Event对象并fire // event.fire(new ExecutionEvent(methodName, result, exception)); } }
步骤3:启用拦截器
在Quarkus中,需要确保拦截器被注册。可以通过src/main/resources/META-INF/beans.xml声明:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd" version="2.0" bean-discovery-mode="all"> </beans>
步骤4:使用拦截器
在需要触发事件的方法上添加@AfterExecution注解即可:
@ApplicationScoped public class MyService { @AfterExecution public String doSomething() { // 业务逻辑 return "success"; } @AfterExecution public void doSomethingThatThrows() throws Exception { throw new Exception("test exception"); } }
补充说明
- CDI事件集成:如果需要触发CDI事件,只需在拦截器中注入
Event<ExecutionEvent>,然后在finally块中调用event.fire(...),其他Bean可以通过@Observes监听该事件。 - 异常处理注意:catch块中重新抛出异常,保证业务方法的异常流程不受拦截器影响,同时在finally中捕获异常信息用于事件。
- 优先级控制:如果有多个拦截器,可以用
@Priority注解指定执行顺序,数值越小优先级越高。
内容的提问来源于stack exchange,提问作者Chexpir
相关产品推荐
相关产品推荐

