Aar*_*lla 29 configuration spring annotations
我有这个弹簧配置:
@Lazy
@Configuration
public class MyAppConfig {
@Foo @Bean
public IFooService service1() { return new SpecialFooServiceImpl(); }
}
Run Code Online (Sandbox Code Playgroud)
如何获取所有注释的bean列表@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" ); }
}
}
Run Code Online (Sandbox Code Playgroud)
但它失败了org.junit.ComparisonFailure: expected:<[[a]]> but was:<[[]]>.为什么?
Avi*_* T. 37
使用getBeansWithAnnotation()方法获取带注释的bean.
Map<String,Object> beans = applicationContext.getBeansWithAnnotation(Foo.class);
Run Code Online (Sandbox Code Playgroud)
这是类似的讨论.
Aar*_*lla 23
在几位Spring专家的帮助下,我找到了一个解决方案:a的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;
}
Run Code Online (Sandbox Code Playgroud)
kaq*_*qao 22
虽然接受的答案和Grzegorz的答案包含适用于所有情况的方法,但我发现一个更简单的方法,对于最常见的情况同样有效.
1)元注释@Foo用@Qualifier:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Foo {
}
Run Code Online (Sandbox Code Playgroud)
2)@Foo如问题中所述,撒上工厂方法:
@Foo @Bean
public IFooService service1() { return new SpecialFooServiceImpl(); }
Run Code Online (Sandbox Code Playgroud)
但它也适用于类型级别:
@Foo
@Component
public class EvenMoreSpecialFooServiceImpl { ... }
Run Code Online (Sandbox Code Playgroud)
3)然后,注入所有合格的实例@Foo,无论其类型和创建方法如何:
@Autowired
@Foo
List<Object> fooBeans;
Run Code Online (Sandbox Code Playgroud)
fooBeans然后将包含由注释@Foo方法生成的所有实例(根据问题的要求),或者从发现的带@Foo注释的类创建.
如果需要,还可以按类型过滤列表:
@Autowired
@Foo
List<SpecialFooServiceImpl> fooBeans;
Run Code Online (Sandbox Code Playgroud)
好的部分是它不会干扰方法的任何其他@Qualifier(元)注释,也不会干扰@Component类型级别的其他(元)注释.它也不会在目标bean上强制执行任何特定名称或类型.
Grz*_*zki 12
仅仅为了使bean注释而@Foo加入a()方法是不够的.a@Foo
在我开始调试Spring代码之前我没有意识到这一点,一个断点org.springframework.beans.factory.support.DefaultListableBeanFactory.findAnnotationOnBean(String, Class<A>)让我理解它.
当然,如果您将注释移动到Named类:
@Foo
public static class Named {
...
Run Code Online (Sandbox Code Playgroud)
并修复了测试的一些小细节(注释目标等)测试的工作原理.
再给它一点想法,这很自然.当getBeansWithAnnotation()被调用时,只有信息春回大地是豆类.而bean是对象,对象有类.Spring似乎不需要存储任何其他信息,包括.什么是用于创建带注释的bean的工厂方法等.
编辑有一个问题要求保留@Bean方法的注释:https://jira.springsource.org/browse/SPR-5611
它已被关闭为"无法解决"以下解决方法:
BeanPostProcessorbeanName提供给BPP方法来查找BeanDefinition封闭的关联BeanFactoryBeanDefinition其factoryBeanName(@Configurationbean)和factoryMethodName(@Bean名称)Method源自的bean| 归档时间: |
|
| 查看次数: |
38547 次 |
| 最近记录: |