2016-01-14 26 views
7

tarafından ApplicationContext gelen fasulye alın:bu kod Verilen ön eleme

public interface Service {} 

@Component 
@Qualifier("NotWanted") 
public class NotWantedService implements Service {} 

@Component 
@Qualifier("Wanted") 
public class WantedService implements Service {} 

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); 
ctx.register(NotWantedService.class); 
ctx.register(WantedService.class); 
ctx.refresh() 

nasıl ne yapacağım: Sadece @Qualifier("Wanted") ile bir ve @Qualifier("NotWanted") ile değil tane alacak şekilde

ctx.getBean(Service.class) 

? Özellikle getBean kullanarak, bir sınıfa enjekte edilmemesini, sonra da bir proxy türü olarak kullanmanın mümkün olup olmadığını soruyorum. ApplicationContext aracılığıyla fasulye alırken

+0

Neden, '("Wanted"), yani' ctx.getBean adı sabiti kullanıyorsanız beri adıyla fasulye almıyor? Size Say @aux – aux

+0

Eğer 'ctx.getBean ("servis1") do 50 yerler var' ve artık 'ctx.getBean ("Service2")' bunu değiştirmek istiyorum. Bu 50 değişiklik. eleme değiştirme 2 fasulye tanımları ('service1' ve' service2') Sadece dönmek için kullanılır. Başka durumlar da var - "Aranıyor" olan birden çok "Hizmet" örneğini almak istiyorum. Hepsi aynı fasulye ismine sahip olamaz. –

+0

Tamam, anlıyorum. O zaman ne yay veri kalanında 'Repositories' gibi fasulye başvurular tutan ve farklı parametreler tarafından arama için kullanılan kendi "kayıt" fasulye, tanıtılması konusunda? Ya da bir sarıcı mı? – aux

cevap

7

O @Qualifier ek açıklamanın amacı kullanmak değil. Ancak, bazı nedenlerle böyle veya benzer bir işleve ihtiyaç duyduğunuz için, bir geçici çözüm öneririm.

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, 
     ElementType.METHOD, ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface Wanted { 
} 

ve

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, 
      ElementType.METHOD, ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface NotWanted { 
} 

bu yeni ek açıklamalarla Fasulye sınıfları ek açıklama:

@Wanted ve @NotWanted ek açıklama oluşturun

@Component 
@NotWanted 
public class NotWantedService implements Service {} 

ve

Böyle

ApplicationContext applicationContext; 

private <T> Collection<T> getBeansByTypeAndAnnotation(Class<T> clazz, Class<? extends Annotation> annotationType){ 
    Map<String, T> typedBeans = applicationContext.getBeansOfType(clazz); 
    Map<String, Object> annotatedBeans = applicationContext.getBeansWithAnnotation(annotationType); 
    typedBeans.keySet().retainAll(annotatedBeans.keySet()); 
    return typedBeans.values(); 
} 

private <T> Optional<T> getBeanByTypeAndAnnotation(Class<T> clazz, Class<? extends Annotation> annotationType) { 
    Collection<T> beans = getBeansByTypeAndAnnotation(clazz, annotationType); 
    return beans.stream().findFirst(); 
} 

Ve şimdi açıklama ile fasulye ya da bir fasulye almak için onları kullanabilir ve yazın::

@Component 
@Wanted 
public class WantedService implements Service {} 

Eğer ApplicationContext erişimi nereye Sonra yere 2 yöntemlerini eklemek gerekir

Collection<Service> services = getBeansByTypeAndAnnotation(Service.class, Wanted.class); 

veya

Service service = getBeanByTypeAndAnnotation(Service.class, Wanted.class); 

Muhtemelen o b değil problemle başa çıkmak için bir yol. Biz 'kutunun dışında' eleme ve türe göre ApplicationContext den fasulye alamıyorsanız beri Ama, bu bunu yapmak için yollarından biridir.

+1

Teşekkürler @Rozart - Bunu zaten denedim. Maalesef, bu, @ Niteleyiciyi dikkate almıyor. Bu aynı değildir '@Bean (adı = "abc") ', belirtilen fasulye adını alır. –

+0

Gerçi '' @Bean (isim = "abc") aynı şey, aynı anlamlara sahip değildir. Aynı adı taşıyan iki fasulyeye sahip olamazsınız, ancak aynı kalitede birden fazlasına sahip olabilirsiniz. Yani, "Wanted" ile nitelendirilen, ancak "Wanted" olarak adlandırılmayan 10 farklı hizmet istiyorum. –

+0

Cevabı güncelledim. Belki bu sana yardım eder. :) – Rozart

2

bağlam @Component ek açıklamada fasulye adını tanımlamak ve bağlamdan adıyla bunu elde etmek için, daha iyi bir yol enjekte değil gelen fasulye almak istiyorsanız. Çoğu durumda @Qualifier enjeksiyonlar için kullanılır.

1

İlkbaharda bunu yapmanın en yakın kanonik yolu BeanFactoryAnnotationUtils yardımcı program sınıfı ile ... ama bu ne yazık ki yalnızca @Qualifier ek açıklama değeri argümanı ile çalışır (bu nedenle argüman neden bir dizgedir).

Ne @Rozart is recommending iyi yaklaşım ve gerçekten bir şey olduğunu BeanFactoryAnnotationUtils olmalıdır gibidir. Sadece durumda birisi yukarıdaki cevabı burada toprakları ve doğrudan @Qualifier (ve onunla birlikte gelen tüm fasulye aliasing) kullanmak istiyor dahil.

Ben baharda bir özellik talebinde bulunabilirsiniz (yapardım ama onlar :-) onları rahatsız eden beni yorgun olabileceğini düşünüyorum).

4

Sen 'qualifiedBeanOfType' yöntemi yalnızca ConfigurableListenableBeanFactory için eleme çözebilirsiniz çünkü ctx.getBeanFactory() değil ctx kendisi kullanmak Bu önemlidir

BeanFactoryAnnotationUtils.qualifiedBeanOfType(ctx.getBeanFactory(), Service.class, "Wanted") 

kullanabilirsiniz.