
本文介绍如何利用 ArchUnit 的元注解(meta-annotation)检查能力,自动禁止非 @Qualifier 类型的类直接使用被 @Qualifier 注解修饰的自定义注解(如 @Custom),从而在编译前保障依赖注入规范。
本文介绍如何利用 archunit 的元注解(meta-annotation)检查能力,自动禁止非 `@qualifier` 类型的类直接使用被 `@qualifier` 注解修饰的自定义注解(如 `@custom`),从而在编译前保障依赖注入规范。
在基于 JSR-330(如 Jakarta CDI 或 Dagger)的依赖注入实践中,@Qualifier 注解具有严格的语义约束:它仅应作为元注解用于定义其他限定符注解(如 @Custom),而绝不应直接标注在业务类、服务类或组件类上。若违反此约定(例如 @Custom class UserService {}),将导致注入歧义或运行时异常,但传统编译器无法捕获——必须借助静态架构验证工具。
ArchUnit 提供了原生支持元注解校验的 API:beMetaAnnotatedWith()。该方法可精准识别“某类是否被一个 自身被 @Qualifier 标注的注解 所标记”。结合 noClasses().that().should() 的否定规则语法,即可构建强约束:
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import javax.inject.Qualifier;
ArchRule noQualifierAnnotationOnNonQualifierTypes =
noClasses()
.that().areNotAnnotatedWith(Qualifier.class) // 排除真正的 @Qualifier 注解类型(如 @Custom 接口本身)
.should().beMetaAnnotatedWith(Qualifier.class); // 但被 @Qualifier 元注解修饰的注解(如 @Custom)却用在了它身上
✅ 关键设计说明:
-
.areNotAnnotatedWith(Qualifier.class)显式排除@interface Custom自身——否则它会因“被@Qualifier标注”而误报; -
.beMetaAnnotatedWith(Qualifier.class)则匹配所有被@Qualifier直接声明在@interface上的注解所标记的类(即@Custom class Test {}中的Test); - 整条规则本质是:“任何 不是
@Qualifier注解 的类型,都不允许使用 源自@Qualifier的限定符注解”。
⚠️ 注意事项:
- 确保
@Custom的@Retention(RUNTIME)保留策略,ArchUnit 依赖反射读取运行时注解; - 若项目中存在多个
@Qualifier衍生注解(如@Primary,@Named,@Mock),本规则将统一拦截其非法使用; - 建议将该规则集成至 Maven/Gradle 的
archunit:test阶段,实现 CI/CD 中的自动门禁。
通过这一简洁而精准的 ArchUnit 规则,你无需手动遍历反射类型,即可在测试阶段 100% 拦截违反 DI 规范的注解滥用,显著提升架构健壮性与团队协作效率。










