如何通过反射获取接口默认方法的注解?TestNG拦截器实践遇阻
解决方案
核心问题是子类继承的默认方法无法直接获取到接口方法上的注解(因为@Ignore没有@Inherited元注解),所以要从接口的方法实例上读取注解。
可行的拦截器实现
修改拦截器逻辑,先判断是否是默认方法,再从接口中获取原方法实例检查注解:
@Override @SneakyThrows public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) { return methods.stream() .filter(methodInstance -> { Method method = methodInstance.getMethod().getConstructorOrMethod().getMethod(); // 非默认方法直接保留 if (!method.isDefault()) { return true; } Class<?> declaringClass = method.getDeclaringClass(); // 不是接口定义的方法,直接保留 if (!declaringClass.isInterface()) { return true; } try { // 获取接口中定义的原方法 Method interfaceMethod = declaringClass.getMethod(method.getName(), method.getParameterTypes()); // 检查接口方法是否有@Ignore,有则过滤 return !interfaceMethod.isAnnotationPresent(Ignore.class); } catch (NoSuchMethodException e) { // 理论上不会触发,直接保留 return true; } }) .collect(Collectors.toList()); }
为什么之前的方法失效?
- 直接调用
method.isAnnotationPresent(Ignore.class)时,这个method是子类继承后的方法对象,Java默认不会继承接口方法的注解(除非注解本身标记了@Inherited,但@Ignore没有)。 AnnotationUtils.findAnnotation需要传入接口的方法实例才能正确扫描到注解,传入子类的方法实例不行。
简化方案(批量忽略所有接口默认方法)
如果不需要单个方法控制,直接过滤所有默认方法即可:
@Override @SneakyThrows public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) { return methods.stream() .filter(it -> !it.getMethod().getConstructorOrMethod().getMethod().isDefault()) .collect(Collectors.toList()); }
内容的提问来源于stack exchange,提问作者javydreamercsw
相关产品推荐
相关产品推荐

