사용자 지정 주석 @Foo가 있는 모든 콩을 어떻게 찾을 수 있습니까?
스프링 구성은 다음과 같습니다.
@Lazy
@Configuration
public class MyAppConfig {
@Foo @Bean
public IFooService service1() { return new SpecialFooServiceImpl(); }
}
주석이 달린 모든 콩의 목록을 가져오려면 어떻게 해야 합니까?@Foo
?
참고:@Foo
사용자 정의 주석입니다.공식적인 봄 주석 중 하나가 아닙니다.
[EDIT] 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:<[[]]>
.왜요?
getBeans 사용주석() 메서드를 사용하여 주석이 있는 콩을 가져옵니다.
Map<String,Object> beans = applicationContext.getBeansWithAnnotation(Foo.class);
여기 비슷한 논의가 있습니다.
업데이트: Spring 5.2는 다음의 동작을 변경했습니다.context.getBeansWithAnnotation(...)
그리고 이제 공장에서 생산된 콩을 올바르게 처리합니다.간단하게 사용해 보세요.
원답
승인된 답변과 Grzegorz의 답변에는 모든 경우에 효과적인 접근법이 포함되어 있지만, 저는 가장 일반적인 경우에도 똑같이 잘 작동하는 훨씬 간단한 접근법을 발견했습니다.
메타 주석
@Foo
와 함께@Qualifier
:@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface Foo { }
뿌리기
@Foo
다음 질문에 설명된 대로 공장 방법에 적용됩니다.@Foo @Bean public IFooService service1() { return new SpecialFooServiceImpl(); }
그러나 유형 수준에서도 작동합니다.
@Foo
@Component
public class EvenMoreSpecialFooServiceImpl { ... }
그런 다음 인증된 모든 인스턴스를 주입합니다.
@Foo
유형 및 작성 방법에 관계없이 다음을 수행할 수 있습니다.@Autowired @Foo List<Object> fooBeans;
fooBeans
그러면 a에 의해 생성된 모든 인스턴스가 포함됩니다.@Foo
- 질문에 필요한 방법 또는 발견된 방법으로 생성됨@Foo
주석이 달린 수업
필요한 경우 유형별로 목록을 추가로 필터링할 수 있습니다.
@Autowired
@Foo
List<SpecialFooServiceImpl> fooBeans;
좋은 점은 다른 어떤 것에도 방해가 되지 않는다는 것입니다.@Qualifier
(viii) 방법에 대한 설명, 또는@Component
유형 수준의 기타 항목.또한 대상 콩에 특정 이름이나 유형을 적용하지 않습니다.
몇 명의 Spring 전문가들의 도움으로, 저는 해결책을 찾았습니다: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;
}
도우미 클래스 및 테스트 사례의 전체 코드가 포함된 요지
단편소설
그것으로는 충분하지 않습니다.@Foo
에서a()
만들기 위한 방법a
주석이 달린@Foo
.
장황한 이야기
스프링 코드 디버깅을 시작하기 전까지는 몰랐습니다.org.springframework.beans.factory.support.DefaultListableBeanFactory.findAnnotationOnBean(String, Class<A>)
이해하는 데 도움이 됐어요
물론 주석을 명명된 클래스로 이동한 경우:
@Foo
public static class Named {
...
테스트의 일부 세부 사항(해석 대상 등)을 수정합니다.
다시 한 번 생각해 본 결과, 그것은 아주 자연스러운 일입니다.언제getBeansWithAnnotation()
라고 불리는데, 봄이 가지고 있는 유일한 정보는 콩입니다.그리고 콩은 물체이고, 물체는 계급을 가지고 있습니다.그리고 Spring은 다음과 같은 추가 정보를 저장할 필요가 없어 보입니다.주석이 달린 콩을 만드는 데 사용된 공장 방법 등은 무엇이었습니까?
EDIT 다음에 대한 주석 보존을 요청하는 문제가 있습니다.@Bean
방법: https://jira.springsource.org/browse/SPR-5611
다음 해결 방법으로 "수정하지 않음"으로 닫혔습니다.
- 용기하를 합니다.
BeanPostProcessor
- 을 합니다.
beanName
된 BPP를 됩니다.BeanDefinition
한 동한것부터로에서.BeanFactory
- 쿼리대 쿼리
BeanDefinition
그것 때문에factoryBeanName
(그)@Configuration
과 콩) 및factoryMethodName
(그)@Bean
으)로 표시) - 반사를 이용하여 그것을 잡습니다.
Method
에서 유래한 것입니다. - 반사를 사용하여 해당 방법의 사용자 정의 주석을 조회합니다.
주석이 달린 모든 콩을 가져오는 방법
context.getBeansWithAnnotation(Foo.class)
이는 다음을 반환합니다.Map<String, Object>
여기서 키는 콩 이름입니다.
주석 클래스를 가져오는 방법
context.findAnnotationOnBean(beanName, Foo.class);
값이 때 이 될 수 .@Foo(weight=100)
).
이것이 주석이 달린 콩을 얻는 방법입니다.
@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);
});
}
경우에는 경에는우내는▁in.getBeansWithAnnotation
빈 목록을 반환했습니다.제 실수는 사용자 지정 주석에 보존 및 대상을 추가하지 않은 것입니다.
이 선들을 추가하는 것은 제 주석의 맨 위에 그것을 수정하지 않았습니다.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
언급URL : https://stackoverflow.com/questions/14236424/how-can-i-find-all-beans-with-the-custom-annotation-foo
'sourcetip' 카테고리의 다른 글
CSS에서 확인란의 테두리 스타일을 변경하는 방법은 무엇입니까? (0) | 2023.08.26 |
---|---|
감사 테이블에 대한 트리거 생성 (0) | 2023.08.26 |
Run As: Spring Boot App과 Run As: Java Application의 차이점이 있습니까? (0) | 2023.08.26 |
Angular/Karma 장치 테스트 오류 "1개의 타이머가 대기열에 있습니다." (0) | 2023.08.26 |
작곡가 레이블에 종속성(docrine/dbal) 설치 (0) | 2023.08.26 |