[SPRING] @Foo 커스텀 어노테이션으로 모든 빈을 어떻게 찾을 수 있습니까?
SPRING@Foo 커스텀 어노테이션으로 모든 빈을 어떻게 찾을 수 있습니까?
나는이 봄 환경을 가지고있다 :
@Lazy
@Configuration
public class MyAppConfig {
@Foo @Bean
public IFooService service1() { return new SpecialFooServiceImpl(); }
}
@Foo로 주석 처리 된 모든 bean 목록을 얻으려면 어떻게해야합니까?
참고 : @Foo는 저에게 정의 된 맞춤 주석입니다. "공식적인"스프링 주석 중 하나가 아닙니다.
[편집] 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]]>로 실패하지만 <: []]>. 왜?
해결법
-
==============================
1.주석이있는 bean을 가져 오려면 getBeansWithAnnotation () 메소드를 사용하십시오.
주석이있는 bean을 가져 오려면 getBeansWithAnnotation () 메소드를 사용하십시오.
Map<String,Object> beans = applicationContext.getBeansWithAnnotation(Foo.class);
다음은 비슷한 토론입니다.
-
==============================
2.몇 명의 스프링 전문가의 도움으로 해결책을 찾았습니다. BeanDefinition의 source 속성은 AnnotatedTypeMetadata가 될 수 있습니다. 이 인터페이스에는 getAnnotationAttributes () 메소드가 있는데,이 메소드를 사용하여 Bean 메소드의 어노테이션을 가져올 수 있습니다.
몇 명의 스프링 전문가의 도움으로 해결책을 찾았습니다. BeanDefinition의 source 속성은 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; }
도우미 클래스 및 테스트 케이스의 전체 코드가있는 요점
-
==============================
3.답변과 Grzegorz의 답변에는 모든 경우에 사용할 수있는 접근법이 포함되어 있지만 가장 일반적인 경우에 똑같이 잘 작동하는 훨씬 단순한 방법을 발견했습니다.
답변과 Grzegorz의 답변에는 모든 경우에 사용할 수있는 접근법이 포함되어 있지만 가장 일반적인 경우에 똑같이 잘 작동하는 훨씬 단순한 방법을 발견했습니다.
1) Meta-annotate @Foo @Qualifier :
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface Foo { }
2) 질문에 설명 된대로 @Foo를 팩토리 메서드에 뿌린다.
@Foo @Bean public IFooService service1() { return new SpecialFooServiceImpl(); }
그러나 또한 유형 수준에서 작동합니다.
@Foo @Component public class EvenMoreSpecialFooServiceImpl { ... }
3) 그런 다음 유형과 작성 방법에 관계없이 @Foo에서 규정 한 모든 인스턴스를 주입하십시오.
@Autowired @Foo List<Object> fooBeans;
그런 다음 fooBeans는 @ Foo 주석이 달린 메소드 (질문에 필요)에 의해 생성되거나 발견 된 @Foo 주석이있는 클래스에서 생성 된 모든 인스턴스를 포함합니다.
필요한 경우 목록을 추가로 필터링 할 수 있습니다.
@Autowired @Foo List<SpecialFooServiceImpl> fooBeans;
좋은 부분은 메소드의 다른 @Qualifier (메타) 주석이나 @Component 및 유형 수준의 다른 주석과 간섭하지 않는다는 것입니다. 또한 대상 빈에 특정 이름이나 유형을 적용하지도 않습니다.
-
==============================
4.@Foo로 주석 처리 된 bean을 만들기 위해 @Foo를 a () 메소드에 두는 것만으로는 충분하지 않습니다.
@Foo로 주석 처리 된 bean을 만들기 위해 @Foo를 a () 메소드에 두는 것만으로는 충분하지 않습니다.
Spring 코드 디버깅을 시작하기 전에는 깨닫지 못했습니다. 중단 점은 org.springframework.beans.factory.support.DefaultListableBeanFactory.findAnnotationOnBean (String, Class )로 이해할 수있었습니다.
물론 주석을 Named 클래스로 옮긴 경우 :
@Foo public static class Named { ...
테스트의 일부 세부 사항 (주석 대상 등)이 수정되었습니다.
두 번째 생각을 한 후, 그것은 아주 자연스러운 일입니다. getBeansWithAnnotation ()이 호출되면 Spring에있는 유일한 정보는 빈입니다. 콩은 객체이고, 객체는 클래스입니다. 그리고 Spring은 추가적인 정보를 저장하는 것을 필요로하지 않는다. 어노테이션 된 bean을 만드는 데 사용 된 팩토리 메소드는 무엇입니까?
편집 @Bean 메서드에 대한 주석을 보존하라는 요청이 있습니다 : https://jira.springsource.org/browse/SPR-5611
다음 해결 방법으로 "수정되지 않음"으로 종료되었습니다.
from https://stackoverflow.com/questions/14236424/how-can-i-find-all-beans-with-the-custom-annotation-foo by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] JSR-303 @Valid 주석 (중첩 된 객체)이 작동하지 않음 (0) | 2018.12.10 |
---|---|
[SPRING] Spring logging DEBUG 메시지를 비활성화하는 방법은 무엇입니까? (0) | 2018.12.10 |
[SPRING] 스프링 3.1이있는 Jackson 2.0 (0) | 2018.12.10 |
[SPRING] @ComponentScan의 특정 패키지 필터링 (0) | 2018.12.10 |
[SPRING] Join 테이블의 추가 속성을 위해 많은 수의 최대 절전 모드 매핑을 만드는 방법은 무엇입니까? (0) | 2018.12.10 |