我想在基於Spring的Web應用程序中搜索一些註釋,如@Entity
。因此,我需要像Spring一樣的功能,當服務器啓動時,它會查找所有使用@Component
進行註釋的類。在我的情況下,我不會創建單例,對於我來說收集所有用@Entity
註解的類是非常重要的。如何複製Spring的組件掃描
有沒有可能使用現有的Spring工具呢?我想在Spring中爲@Component
註釋準確地搜索相同的名稱空間。
我想在基於Spring的Web應用程序中搜索一些註釋,如@Entity
。因此,我需要像Spring一樣的功能,當服務器啓動時,它會查找所有使用@Component
進行註釋的類。在我的情況下,我不會創建單例,對於我來說收集所有用@Entity
註解的類是非常重要的。如何複製Spring的組件掃描
有沒有可能使用現有的Spring工具呢?我想在Spring中爲@Component
註釋準確地搜索相同的名稱空間。
Spring的內置類路徑掃描基礎結構(ClassPathBeanDefinitionScanner/ComponentScanBeanDefinitionParser)專門用於在Spring appcontext中將類註冊爲BeanDefinitions。
如果您只是希望獲得使用給定註釋註釋的類列表(而不是實際在Spring中將它們註冊爲bean定義),請查看Google Reflections庫。
反射允許您使用各種過濾器(包括註釋過濾器)來掃描您的類路徑。
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeClassOrInterface>> subTypes = reflections.getSubTypesOf(SomeClassOrInterface.class);
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);
當然,請看parse()
方法org.springframework.context.annotation.ComponentScanBeanDefinitionParser
。當Spring在XML配置中遇到<context:component-scan/>
時,將調用此方法。可能你可以剝掉它來更好地滿足你的需求,但它應該成爲一個綜合的例子。
你應該特別感興趣的課程是org.springframework.context.annotation.ClassPathBeanDefinitionScanner
。來自JavaDoc:
通過可配置的類型過濾器檢測候選類。默認過濾器包括使用Spring的@Component,@Repository,@Service或@Controller構造型進行註釋的類。
順便說一句,如果你需要較少的一般解決方案,也許你的持久性提供者有一些API來獲取所有實體類?
感謝您的建議,托馬斯。在做了一些研究之後,我發現Andrew的建議更加靈活,這就是爲什麼我現在使用Reflections – 2011-03-21 06:30:38
春季基礎的解決方案
使用的FQN
AnnotatedClassFinder entityScanner = new AnnotatedClassFinder(Entity.class);
entityScanner.setPackages(Arrays.asList("org.myapp.domain"));
Collection<Class<?>> entities = entityScanner.findMarkedClassOfType();
public class AnnotatedClassFinder {
private static final String CLASS_RESOURCE_PATTERN = "**/*.class";
private List<String> packages;
private final ResourceLoader resourceLoader = new DefaultResourceLoader();
private final ResourcePatternResolver resourcePatternResolver = ResourcePatternUtils
.getResourcePatternResolver(resourceLoader);
private final MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
private final TypeFilter annotationFilter;
public AnnotatedClassFinder(final Class<? extends Annotation> annotationToScanFor) {
annotationFilter = new AnnotationTypeFilter(annotationToScanFor);
}
public Set<Class<?>> findMarkedClassOfType() {
if (packages == null) {
return new HashSet<Class<?>>();
}
final Set<Class<?>> annotatedClasses = new HashSet<Class<?>>();
try {
for (final String p : packages) {
final String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(p)) + "/"
+ CLASS_RESOURCE_PATTERN;
final Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
for (final Resource resource : resources) {
if (resource.isReadable()) {
final MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
if (annotationFilter.match(metadataReader, metadataReaderFactory)) {
annotatedClasses.add(Class.forName(metadataReader.getAnnotationMetadata().getClassName()));
}
}
}
}
return annotatedClasses;
} catch (final IOException ex) {
throw new RuntimeException("I/O failure during classpath scanning", ex);
} catch (final ClassNotFoundException ex) {
throw new RuntimeException("Class loading failure during classpath scanning", ex);
}
}
public void setPackages(final List<String> packages) {
this.packages = packages;
}
}
此解決方案是對AnnotationSessionFactoryBean的修改 – dasbh 2012-01-04 19:15:21
謝謝dasbh提供僅使用Spring框架的答案。這是我最初的願望,但現在我沒有任何機會去測試它,但無論如何+1。再次感謝。 – 2012-01-06 00:31:10
親愛的安德魯,我現在使用你的Reflections項目,因爲它比Spring的註解解析更靈活。非常感謝你! – 2011-03-21 06:28:28