2008/10/22

Scan package

很多时候,需要动态的检查某个package下是否包含特定的类,比如继承了某个接口,或是附加上了某个annotation。

这是个典型的听上去容易,做起来麻烦的任务。

如果package的classpath属于file://一类,可以直接使用Class.getResourceAsStream("your/package")打开一个text stream, 其中的每一行为package包含的每一个元素。

import scala.io.{Source}

for(
line <- Source.fromInputStream(aClass.getResourceAsStream("your/package")).getLines
name = line.trim
if match(name)
}yield{
Class.forName(name)
}

但是如果package位于某一个jar文件中则需要遍历jar file中对应的每一个jar entry。

庆幸的是,始终可以在open source社区中找到"先人"的贡献。

如果你使用Spring (v 2+),一定会对Spring中新增的annotation wire印象深刻,其中包括一个自动在某个package下寻找符合条件的bean的功能。

这个package scanning的功能由org.springframework.context.annotation.ClassPathBeanDefinitionScanner这个类来完成。默认的设定是找出指定package下带有@Component的类。不过由于Spring良好的结构,很容易进行扩展。


val reg = new SimpleBeanDefinitionRegistry
val scanner = new ClassPathBeanDefinitionScanner(reg, false)
scanner.setIncludeAnnotationConfig(false)
scanner.addIncludeFilter(new AssignableTypeFilter(classOf[Object]))
scanner.scan("your.pkg")

Scanner依赖一个TypeFilter来选择感兴趣的类。在上面的代码中禁止了预先设置的filter,并且用一个AssignableTypeFilter来代替,因此选择所有的类。
一旦scan结束,找到的类定义(BeanDefinition)会被放入BeanDefinitionRegistry这样一个结构中。上面的代码中,使用了SimpleBeanDefinitionRegistry这样一个简单的实现。

0 comments:

Footer

  © Blogger template 'Grease' by Ourblogtemplates.com 2008

Back to TOP