上海比较好的网站建设公司,停止wordpress,淘宝网站建设目标是什么意思,海口网站建设兼职Quarkus 基于CDI和拦截器实现AOP功能#xff08;进阶版#xff09; 拦截器的属性成员拦截器的重复使用基于属性成员和重复使用的拦截器的发消息案例 本节来了解一下拦截器高级特性#xff08;拦截器的重复使用和属性成员#xff09;#xff0c;官网说明#xff1a;https:… Quarkus 基于CDI和拦截器实现AOP功能进阶版 拦截器的属性成员拦截器的重复使用基于属性成员和重复使用的拦截器的发消息案例 本节来了解一下拦截器高级特性拦截器的重复使用和属性成员官网说明https://cn.quarkus.io/guides/cdi-reference#repeatable-interceptor-bindings。
拦截器的属性成员
拦截器自己是个注解而注解是有属性的所以我们时可以在自定义的拦截器注解中添加属性成员的这样在拦截器使用的时候有更多扩展空间。 注意很重要quarkus对属性成员使用时的限制是这些属性成员必须是要被Nonbinding注解所标注的否则在使用有设置属性的拦截器时该拦截器功能不会生效。 Nonbinding 注解用于 CDIContexts and Dependency Injection中的自定义注解以标记不影响注解唯一性的属性。换句话说当你使用 InterceptorBinding 创建自定义注解并将其应用于拦截器时默认情况下所有属性都参与注解的唯一性判断。这意味着如果两个注解的属性值不同它们将被视为不同的注解。有时你可能希望某些属性不影响注解的唯一性。这时你就可以使用 Nonbinding 注解这些属性使其在比较注解时被忽略。当你创建自定义注解并在拦截器上使用时如果该注解有属性且这些属性未被标记为 Nonbinding这些属性将会影响注解的唯一性判断。这意味着拦截器上使用的注解和方法上使用的注解必须完全一致包括所有属性的值否则拦截器不会生效。在自定义注解的属性上添加 Nonbinding 注解使这些属性不影响注解的唯一性判断。这样拦截器上使用的注解和方法上使用的注解可以被认为是相同的即使它们的属性值不同这样拦截器就会生效。 示例代码
package com.xxx.interceptor;import javax.enterprise.util.Nonbinding;
import javax.interceptor.InterceptorBinding;
import java.lang.annotation.*;InterceptorBinding
Target({ElementType.TYPE, ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
public interface SendMessage {/*** 消息类型 : sms表示短信email表示邮件*/NonbindingString sendType() default sms;
}拦截器的重复使用
允许在同一位置重复使用同一个注解这是java注解的通用功能并非quarkus独有但是在quarkus中使用时有些需要注意的限制。
quarkus对重复使用同一拦截器注解的限制
可以作用在方法上不能作用在类上不能作用在stereotypes上
关于2和3官方的说法是将来会解决This might be added in the future
示例代码
package com.bolingcavalry.interceptor.define;import javax.enterprise.util.Nonbinding;
import javax.interceptor.InterceptorBinding;
import java.lang.annotation.*;InterceptorBinding
Repeatable(SendMessage.SendMessageList.class)
Target({ElementType.TYPE, ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
public interface SendMessage {/*** 消息类型 : sms表示短信email表示邮件*/NonbindingString sendType() default sms;Target({ElementType.TYPE, ElementType.METHOD})Retention(RetentionPolicy.RUNTIME)interface SendMessageList {SendMessage[] value();}
}基于属性成员和重复使用的拦截器的发消息案例
要求设计一个拦截器名为SendMessage功能是对外发送通知通知的方式有短信和邮件两种具体用哪种是可以通过拦截器属性设置的。
有个SendMsg的普通接口此接口有三个实现类SendMsgA、SendMsgB、SendMsgC这些实现类都是bean代码如下
public interface SendMsg {String send();
}ApplicationScoped
Named(A)
public class SendMsgA implements SendMsg {Overridepublic void send() {Log.info(send from A);}
}ApplicationScoped
Named(B)
public class SendMsgB implements SendMsg {Overridepublic void send() {Log.info(send from B);}
}ApplicationScoped
Named(C)
public class SendMsgC implements SendMsg {Overridepublic void send() {Log.info(send from C);}
}
需求
用SendMessage拦截器拦截SendMsgA通知类型是短信用SendMessage拦截器拦截SendMsgB通知类型是邮件用SendMessage拦截器拦截SendMsgC通知类型是短信和邮件都发送
代码
package com.xxx.interceptor;import javax.enterprise.util.Nonbinding;
import javax.interceptor.InterceptorBinding;
import java.lang.annotation.*;InterceptorBinding
Repeatable(SendMessage.SendMessageList.class)
Target({ElementType.TYPE, ElementType.METHOD})
Retention(RetentionPolicy.RUNTIME)
public interface SendMessage {/*** 消息类型 : sms表示短信email表示邮件*/NonbindingString sendType() default sms;Target({ElementType.TYPE, ElementType.METHOD})Retention(RetentionPolicy.RUNTIME)interface SendMessageList {SendMessage[] value();}
}
package com.xxx.interceptor.impl;import com.xxx.interceptor.SendMessage;
import com.xxx.interceptor.TrackParams;
import io.quarkus.arc.Priority;
import io.quarkus.arc.runtime.InterceptorBindings;
import io.quarkus.logging.Log;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import java.lang.annotation.Annotation;
import java.util.*;
import static io.quarkus.arc.ArcInvocationContext.KEY_INTERCEPTOR_BINDINGS;SendMessage
Interceptor
public class SendMessageInterceptor {AroundInvokeObject execute(InvocationContext context) throws Exception {// 取出所有注解,由于允许重复注解因此通知类型可能有多个SetAnnotation bindings InterceptorBindings.getInterceptorBindings(invocationContext);// 获取被拦截方法的类名String interceptedClass context.getTarget().getClass().getSimpleName();// ...// 先执行被拦截的方法Object rlt context.proceed();// ...// 最后再返回方法执行结果return rlt;}
} ApplicationScoped
Named(A)
public class SendMsgA implements SendMsg {SendMessageOverridepublic void send() {Log.info(send from A);}
}ApplicationScoped
Named(B)
public class SendMsgB implements SendMsg {SendMessage(sendType email)Overridepublic void send() {Log.info(send from B);}
}// 注意这里使用了两次SendMessage
ApplicationScoped
Named(C)
public class SendMsgC implements SendMsg {SendMessageSendMessage(sendType email)Overridepublic void send() {Log.info(send from C);}
}