如何使用自定义注释 @Foo 找到所有 bean? [英] How can I find all beans with the custom annotation @Foo?

查看:18
本文介绍了如何使用自定义注释 @Foo 找到所有 bean?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个弹簧配置:

@Lazy@配置公共类 MyAppConfig {@Foo @豆public IFooService service1() { return new SpecialFooServiceImpl();}}

如何获取所有带有 @Foo 注释的 bean 的列表?

注意:@Foo 是我自己定义的自定义注解.它不是官方"的 Spring 注释之一.

按照 Avinash T. 的建议,我编写了这个测试用例:

导入静态 org.junit.Assert.*;导入 java.lang.annotation.ElementType;导入 java.lang.annotation.RetentionPolicy;导入 java.lang.annotation.Target;导入 java.lang.annotation.Retention;导入java.lang.reflect.Method;导入 java.util.Map;导入 org.junit.Test;导入 org.springframework.beans.factory.config.BeanDefinition;导入 org.springframework.context.annotation.AnnotationConfigApplicationContext;导入 org.springframework.context.annotation.Bean;导入 org.springframework.context.annotation.Configuration;导入 org.springframework.context.annotation.Lazy;公共类 CustomAnnotationsTest {@测试公共无效 testFindByAnnotation() 抛出异常 {AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext(CustomAnnotationsSpringCfg.class);方法 m = CustomAnnotationsSpringCfg.class.getMethod("a");断言非空(米);assertNotNull(m.getAnnotation(Foo.class));BeanDefinition bdf = appContext.getBeanFactory().getBeanDefinition("a");//有没有办法列出 bdf 的所有注解?映射<字符串,对象>beans = appContext.getBeansWithAnnotation(Foo.class);assertEquals("[a]", beans.keySet().toString());}@Retention(RetentionPolicy.RUNTIME)@目标(元素类型.方法)公共静态@interface Foo {}公共静态类命名{私有最终字符串名称;公共命名(字符串名称){this.name = 名称;}@覆盖公共字符串 toString() {返回名称;}}@懒惰的@配置公共静态类 CustomAnnotationsSpringCfg {@Foo @Bean public Named a() { return new Named( "a" );}@Bean public Named b() { return new Named( "b" );}}}

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

解决方案

在几个 Spring 专家的帮助下,我找到了一个解决方案:BeanDefinition 的 source 属性

code> 可以是 AnnotatedTypeMetadata.这个接口有一个方法 getAnnotationAttributes() 我可以用它来获取一个 bean 方法的注解:

公开列表<字符串>getBeansWithAnnotation(Class type, Predicate> attributeFilter) {列表<字符串>结果 = Lists.newArrayList();ConfigurableListableBeanFactory factory = applicationContext.getBeanFactory();for( 字符串名称 : factory.getBeanDefinitionNames() ) {BeanDefinition bd = factory.getBeanDefinition(name);if(bd.getSource() instanceof AnnotatedTypeMetadata ) {AnnotatedTypeMetadata 元数据 = (AnnotatedTypeMetadata) bd.getSource();映射<字符串,对象>属性 = metadata.getAnnotationAttributes(type.getName());如果(空==属性){继续;}if(attributeFilter.apply(attributes)){结果.add(名称);}}}返回结果;}

gist 以及帮助类和测试用例的完整代码

I have this spring configuration:

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

How can I get a list of all beans that are annotated with @Foo?

Note: @Foo is a custom annotation defined by me. It's not one of the "official" Spring annotations.

[EDIT] Following the suggestions of Avinash T., I wrote this test case:

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" ); }
    }
}

but it fails with org.junit.ComparisonFailure: expected:<[[a]]> but was:<[[]]>. Why?

解决方案

With the help of a couple of Spring experts, I found a solution: The source property of a BeanDefinition can be AnnotatedTypeMetadata. This interface has a method getAnnotationAttributes() which I can use to get the annotations of a bean method:

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;
}

gist with full code of helper class and test case

这篇关于如何使用自定义注释 @Foo 找到所有 bean?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆