背景
先上package结构图,如下

现象
public void testAnnotationType() {
Reflections reflections = new Reflections(
new ConfigurationBuilder()
.setScanners(
new TypeAnnotationsScanner(), // 设置Annotation的Scanner.
new SubTypesScanner() // 设置扫描子类型的scanner.
)
.setUrls(ClasspathHelper.forPackage("com.reflections.anno")) // 设置需要扫描的包,虽然指定了包路径,但是其实还是扫描整个root路径.
.filterInputsBy(new FilterBuilder().includePackage("com.reflections.anno")) // 因为上面的原因,所以这里加上了inputs过滤器
);
Set<Class<?>> types = reflections.getTypesAnnotatedWith(ServiceMode.class); // 获取被@ServiceMode标记的类.
for (Class<?> type : types) {
System.out.println(type.getName());
}
}
执行上面的代码,就会出现异常,如下图所示:

分析
通过异常信息和异常栈来看,应该是SubTypesScanner没有配置,但是我们代码里面是在ConfigurationBuilder里面配置了SubTypeScanner的.因此只能通过查看源码来进行解析了.
这里先看Reflections类的469行.

然后我们查看Store的39行.

所以我们需要查找的问题就变成了为什么storeMap.get("SubTypesScanner")查不到相应的数据.
我们从源头,也就是Reflections类的源码开始.
采用Configuration作为参数的构造函数如下.主要方法是scan();
public Reflections(final Configuration configuration) {
this.configuration = configuration;
store = new Store();
if (configuration.getScanners() != null && !configuration.getScanners().isEmpty()) {
//inject to scanners
for (Scanner scanner : configuration.getScanners()) {
scanner.setConfiguration(configuration);
}
scan();
if (configuration.shouldExpandSuperTypes()) {
expandSuperTypes();
}
}
}
由于代码调用链较长,这里直接查看SubTypeScanner的scan(final Object cls, Store store)方法
// 这里的store是Reflections中store,就是一个存储扫描结果的容器.
@SuppressWarnings({"unchecked"})
public void scan(final Object cls, Store store) {
String className = getMetadataAdapter().getClassName(cls);
String superclass = getMetadataAdapter().getSuperclassName(cls);
if (acceptResult(superclass)) { // debug发现这里返回false.
put(store, superclass, className); // *将相应的信息放入store*
}
for (String anInterface : (List<String>) getMetadataAdapter().getInterfacesNames(cls)) {
if (acceptResult(anInterface)) {
put(store, anInterface, className);
}
}
}
acceptResult方法代码如下
public boolean acceptResult(final String fqn) {
return fqn != null && resultFilter.test(fqn); // 这里的fqn为java.lang.Object
}
debug到这里的时候,发现resultFilter.test(fqn)为false.于是查看了resultFilter,发现在AbstractScanner抽象类中是默认返回true的,也就是说有地方对resultFilter重新进行了赋值才导致校验不通过,所以store中没有SubTypesScanner相关的数据.

仔细检查之后发现,如下图.

此时store中的数据应该是如下图:

原因梳理:首先是因为我设置了InputsFilter,因此会被扫描的类就只有AnnotationA和AnnotationB,而又因为AnnotationA和AnnotationB的父类都是Object,因此这两个类就都不会被SubTypesScanner写入store中,只会被TypeAnnotationsScanner写入store中.而调用reflections.getTypesAnnotatedWith(ServiceMode.class)时,又会通过SubTypesScanner去查询,此时storeMap.get("SubTypesScanner")是null,因此才会抛出异常
解决办法
通过上面分析之后,可以发现,要想不报错,只需要保证storeMap.get("SubTypesScanner")不为null就可以.因此解决办法如下图.

此时storeMap的数据如下.
