41

私はこの春の構成を持っています:

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

で注釈が付けられたすべての Bean のリストを取得するにはどうすればよい@Fooですか?

注:@Fooは私が定義したカスタム アノテーションです。これは、「公式の」Spring アノテーションの 1 つではありません。

[編集] 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:<[[]]>ます。なんで?

4

5 に答える 5

48

getBeansWithAnnotation()メソッドを使用して、アノテーション付きの Bean を取得します。

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

ここに同様の議論があります。

于 2013-01-09T13:43:20.557 に答える
13

ショートストーリー

で注釈を付けた Beanを作成する@Fooには、a()メソッドを配置するだけでは十分ではありません。a@Foo

長い話

Spring コードのデバッグを始める前は気がつきませんでしたが、ブレークポイントがorg.springframework.beans.factory.support.DefaultListableBeanFactory.findAnnotationOnBean(String, Class<A>)理解に役立ちました。

もちろん、注釈を Named クラスに移動した場合:

  @Foo
  public static class Named {
  ...

テストのいくつかの細かい詳細 (注釈ターゲットなど) を修正し、テストが機能するようにしました。

よくよく考えてみると、それはごく自然なことです。が呼び出されたときgetBeansWithAnnotation()、Spring が持つ唯一の情報は Bean です。Bean はオブジェクトであり、オブジェクトにはクラスがあります。また、Spring は追加情報を保存する必要がないようです。アノテーションが付けられた Bean を作成するために使用されたファクトリ メソッドは何でしたかなど。

編集メソッドの注釈を保持するように要求する問題があります@Bean: https://jira.springsource.org/browse/SPR-5611

次の回避策により、「修正されません」としてクローズされました。

  • 採用するBeanPostProcessor
  • beanNameBPP メソッドに提供された を使用してBeanDefinition、囲みから関連付けられた を検索します。BeanFactory
  • BeanDefinitionそのfactoryBeanName( @ConfigurationBean) とfactoryMethodName(@Bean名前)をクエリします。
  • リフレクションを使用してMethod、元の Beanを取得します
  • リフレクションを使用して、そのメソッドからのカスタム アノテーションを問い合わせる
于 2013-01-09T23:43:48.783 に答える
0

これは、注釈付きの Bean を取得する方法です。

@Autowired
private ApplicationContext ctx;

public void processAnnotation() {
    // Getting annotated beans with names
    Map<String, Object> allBeansWithNames = ctx.getBeansWithAnnotation(TestDetails.class);
    //If you want the annotated data
    allBeansWithNames.forEach((beanName, bean) -> {
        TestDetails testDetails = (TestDetails) ctx.findAnnotationOnBean(beanName, TestDetails.class);
        LOGGER.info("testDetails: {}", testDetails);
    });
}
于 2019-05-03T07:45:02.027 に答える