2011-03-17 53 views
2

我想在基於Spring的Web應用程序中搜索一些註釋,如@Entity。因此,我需要像Spring一樣的功能,當服務器啓動時,它會查找所有使用@Component進行註釋的類。在我的情況下,我不會創建單例,對於我來說收集所有用@Entity註解的類是非常重要的。如何複製Spring的組件掃描

有沒有可能使用現有的Spring工具呢?我想在Spring中爲@Component註釋準確地搜索相同的名稱空間。

回答

4

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); 
+0

親愛的安德魯,我現在使用你的Reflections項目,因爲它比Spring的註解解析更靈活。非常感謝你! – 2011-03-21 06:28:28

5

當然,請看parse()方法org.springframework.context.annotation.ComponentScanBeanDefinitionParser。當Spring在XML配置中遇到<context:component-scan/>時,將調用此方法。可能你可以剝掉它來更好地滿足你的需求,但它應該成爲一個綜合的例子。

你應該特別感興趣的課程是org.springframework.context.annotation.ClassPathBeanDefinitionScanner。來自JavaDoc:

通過可配置的類型過濾器檢測候選類。默認過濾器包括使用Spring的@Component,@Repository,@Service或@Controller構造型進行註釋的類。

順便說一句,如果你需要較少的一般解決方案,也許你的持久性提供者有一些API來獲取所有實體類?

+0

感謝您的建議,托馬斯。在做了一些研究之後,我發現Andrew的建議更加靈活,這就是爲什麼我現在使用Reflections – 2011-03-21 06:30:38

1

春季基礎的解決方案

  • 使用Spring AnnotationTypeFilter和使用ResourcePatternResolver加載所有resouces(的.class)給出pacakage
  • 使用SimpleMetadataReaderFactory下獲得MetadataReader
  • 通過Entity.class作爲annotationType
  • 您可以使用MetadataReader調用每個資源上的匹配AnnotationTypeFilter
  • metadataReader.getAnnotationMetadata()。getClassName()將提供一流的

使用的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; 
    } 

} 
+1

此解決方案是對AnnotationSessionFactoryBean的修改 – dasbh 2012-01-04 19:15:21

+0

謝謝dasbh提供僅使用Spring框架的答案。這是我最初的願望,但現在我沒有任何機會去測試它,但無論如何+1。再次感謝。 – 2012-01-06 00:31:10