我有这个春天的配置:
@Lazy @Configuration public class MyAppConfig { @Foo @Bean public IFooService service1() { return new SpecialFooServiceImpl(); } }
如何获得所有带有注释的bean的列表@Foo?
@Foo
注意:@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:<[[]]>。为什么?
org.junit.ComparisonFailure: expected:<[[a]]> but was:<[[]]>
一对夫妇spring专家的帮助下,我找到了一个解决方案:source的属性BeanDefinition可以AnnotatedTypeMetadata。这个接口有一个getAnnotationAttributes()我可以用来获取bean方法的注释的方法:
source
BeanDefinition
AnnotatedTypeMetadata
getAnnotationAttributes()
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; }
使用getBeansWithAnnotation()方法获取带有注释的bean。
getBeansWithAnnotation()
Map<String,Object> beans = applicationContext.getBeansWithAnnotation(Foo.class);