如何找到所有带有自定义注解@Foo 的bean?

新手上路,请多包涵

我有这个弹簧配置:

 @Lazy
@Configuration
public class MyAppConfig {
    @Foo @Bean
    public IFooService service1() { return new SpecialFooServiceImpl(); }
}

我怎样才能得到所有用 @Foo 注释的 bean 的列表?

注意: @Foo 是我定义的自定义注解。它不是“官方”Spring 注释之一。

[编辑] 根据 Avinash T. 的建议,我编写了这个测试用例:

 import static org.junit.Assert.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import java.lang.annotation.Retention;
import java.lang.reflect.Method;
import java.util.Map;
import org.junit.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

public class CustomAnnotationsTest {

    @Test
    public void testFindByAnnotation() throws Exception {

        AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext( CustomAnnotationsSpringCfg.class );

        Method m = CustomAnnotationsSpringCfg.class.getMethod( "a" );
        assertNotNull( m );
        assertNotNull( m.getAnnotation( Foo.class ) );

        BeanDefinition bdf = appContext.getBeanFactory().getBeanDefinition( "a" );
        // Is there a way to list all annotations of bdf?

        Map<String, Object> beans = appContext.getBeansWithAnnotation( Foo.class );
        assertEquals( "[a]", beans.keySet().toString() );
    }

    @Retention( RetentionPolicy.RUNTIME )
    @Target( ElementType.METHOD )
    public static @interface Foo {

    }

    public static class Named {
        private final String name;

        public Named( String name ) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    @Lazy
    @Configuration
    public static class CustomAnnotationsSpringCfg {

        @Foo @Bean public Named a() { return new Named( "a" ); }
             @Bean public Named b() { return new Named( "b" ); }
    }
}

但它失败了 org.junit.ComparisonFailure: expected:<[[a]]> but was:<[[]]> 。为什么?

原文由 Aaron Digulla 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 431
2 个回答

在几个 Spring 专家的帮助下,我找到了一个解决方案: source 的属性 BeanDefinition 可以是 AnnotatedTypeMetadata 。这个接口有一个方法 getAnnotationAttributes() 我可以用它来获取bean方法的注释:

 public List<String> getBeansWithAnnotation( Class<? extends Annotation> type, Predicate<Map<String, Object>> attributeFilter ) {

    List<String> result = Lists.newArrayList();

    ConfigurableListableBeanFactory factory = applicationContext.getBeanFactory();
    for( String name : factory.getBeanDefinitionNames() ) {
        BeanDefinition bd = factory.getBeanDefinition( name );

        if( bd.getSource() instanceof AnnotatedTypeMetadata ) {
            AnnotatedTypeMetadata metadata = (AnnotatedTypeMetadata) bd.getSource();

            Map<String, Object> attributes = metadata.getAnnotationAttributes( type.getName() );
            if( null == attributes ) {
                continue;
            }

            if( attributeFilter.apply( attributes ) ) {
                result.add( name );
            }
        }
    }
    return result;
}

具有帮助程序类和测试用例的完整代码的要点

原文由 Aaron Digulla 发布,翻译遵循 CC BY-SA 4.0 许可协议

使用 getBeansWithAnnotation() 方法获取带注解的 bean。

 Map<String,Object> beans = applicationContext.getBeansWithAnnotation(Foo.class);

是类似的讨论。

原文由 Avinash T. 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题