【问题标题】:Java annotation scanning with spring使用spring进行Java注解扫描
【发布时间】:2012-05-19 22:30:44
【问题描述】:

我需要用名称注释的类很少,因此我将注释定义为

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface JsonUnmarshallable {
    public String value();
}

现在需要这个注解的类被定义为

@JsonUnmarshallable("myClass")
public class MyClassInfo {
<few properties>
}

我使用下面的代码来扫描注释

private <T> Map<String, T> scanForAnnotation(Class<JsonUnmarshallable> annotationType) {
    GenericApplicationContext applicationContext = new GenericApplicationContext();
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(applicationContext, false);
    scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
    scanner.scan("my");
    applicationContext.refresh();
    return (Map<String, T>) applicationContext.getBeansWithAnnotation(annotationType);
}

问题是返回的映射包含["myClassInfo" -&gt; object of MyClassInfo],但我需要映射包含"myClass" 作为键,这是注释的值而不是bean 名称。

有没有办法做到这一点?

【问题讨论】:

    标签: java spring annotations applicationcontext


    【解决方案1】:

    在我的情况下,我写如下:

    ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
    scanner.addIncludeFilter(new AnnotationTypeFilter(JsonUnmarshallable.class));
    Set<BeanDefinition> definitions = scanner.findCandidateComponents("base.package.for.scanning");
    
    for(BeanDefinition d : definitions) {
        String className = d.getBeanClassName();
        String packageName = className.substring(0,className.lastIndexOf('.'));
        System.out.println("packageName:" + packageName + " , className:" + className);
    }
    

    【讨论】:

      【解决方案2】:

      只要拿到注解对象,拉出值就行了

      Map<String,T> tmpMap = new HashMap<String,T>();
      JsonUnmarshallable ann;
      for (T o : applicationContext.getBeansWithAnnotation(annotationType).values()) {
          ann = o.getClass().getAnnotation(JsonUnmarshallable.class);
          tmpMap.put(ann.value(),o);
      }
      return o;
      

      如果不清楚,请告诉我。

      【讨论】:

        【解决方案3】:

        您可以向 ClassPathBeanDefinitionScanner 提供自定义 BeanNameGenerator,它可以查找您的注释值并将其作为 bean 名称返回。

        我认为按照这些思路的实现应该适合你。

        package org.bk.lmt.services;
        
        import java.util.Map;
        import java.util.Set;
        
        import org.springframework.context.annotation.AnnotationBeanNameGenerator;
        public class CustomBeanNameGenerator extends AnnotationBeanNameGenerator{
            @Override
            protected boolean isStereotypeWithNameValue(String annotationType,
                    Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
        
                return annotationType.equals("services.JsonUnmarshallable");
            }
        }
        

        将此添加到您之前的扫描仪代码中: scanner.setBeanNameGenerator(new CustomBeanNameGenerator());

        【讨论】:

          【解决方案4】:

          也许您可以使用http://scannotation.sourceforge.net/ 框架来实现。

          希望对你有帮助。

          【讨论】:

          • 我尝试使用该框架,它更灵活,但我找不到特定于我的用例。你能告诉我如何让 annotationDb 返回一个由类中定义的 annotation 的值键控的 Map
          猜你喜欢
          • 2011-07-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多